3 回答
TA贡献1848条经验 获得超10个赞
Go 的调度程序将挂起等待系统调用的 goroutine,并在系统调用完成时唤醒它们,为您提供一个同步 API 来处理异步调用。
阅读有关调度程序如何工作的更多信息。
然而,没有确切的方法来确定哪个 goroutine 将被一个接一个地唤醒或将控制权从一个 goroutine 直接交给另一个 goroutine - 这是调度程序的工作。
您关心的是 Go 中已解决的问题,您不必担心 - 代码消失!
编辑:
进一步澄清;你不应该编码以符合(或更好地利用)Go 的调度程序的语义——而是相反。今天可能有一些代码技巧可以让您略微提高性能,但调度程序可以并且会在任何未来的 Go 版本中改变——使您的代码优化无用,甚至对您不利。
TA贡献1859条经验 获得超6个赞
两种机制可以增强您对此的控制:
runtime.Gosched() - 将控制权交还给调度程序,但当然它对您已经发出的阻塞调用没有帮助。
runtime.LockOSThread()将一个真正的 OS 线程专门用于这个 goroutine 而不是其他的,这意味着调度程序中的竞争会减少。从文档:
LockOSThread wires the calling goroutine to its current operating system thread. Until the calling goroutine exits or calls UnlockOSThread, it will always execute in that thread, and no other goroutine can.
TA贡献2016条经验 获得超9个赞
通过 Go 1.1,goroutines 只会对阻塞调用(系统调用、通道读/写、互斥锁等)产生控制。这意味着 goroutine 理论上可以完全占用 CPU,并且不允许调度程序运行。
在 Go 1.2 中,引入了一个更改来解决这个问题:
在之前的版本中,一个永远循环的 goroutine 可能会使同一线程上的其他 goroutine 饿死,当 GOMAXPROCS 只提供一个用户线程时,这是一个严重的问题。在 Go 1.2 中,这部分得到了解决:在进入函数时偶尔会调用调度程序。这意味着任何包含(非内联)函数调用的循环都可以被抢占,允许其他 goroutine 在同一线程上运行。
从理论上讲,通过从不调用非内联函数,仍然有可能让 goroutines 占用 CPU,但这种情况比从不进行阻塞调用的goroutines 少得多,这是在 Go 1.2 之前得到的。
- 3 回答
- 0 关注
- 242 浏览
添加回答
举报