据我所知,如果他们太忙,goroutines会阻止其他goroutines运行.对我来说,这意味着我的应用程序的性能和响应性可能取决于我知道哪些库方法将控制其他goroutine(例如通常是Read()和Write())
有什么方法我可以确切地知道不同的库方法将如何控制其他goroutine,即实际上没有阻止?
有没有办法可以实现一个调用第三方代码的新方法(包括依赖于waitforsingleobject或waitformultipleobjects的异步Win32 API,如findnextchangenotification),并且对Go调度程序表现"不错"?在这个特定的例子中,系统调用将在完成后发出信号,我需要等到它完成后不会耗尽所有其他goroutine.
是否还有另一个"最佳实践",如何处理Go中的第三方阻止操作,以便它们不会耗尽其他goroutines?
我假设Go运行时可能在后台线程上内部运行某种IO循环,以便"暂停"阻止goroutine操作,直到它们完成IO.如果情况确实如此,那么我认为能够在此基础上进行新的阻塞操作可能是有用的.
thw*_*hwd 13
Go的调度程序将暂停正在等待系统调用的goroutine,并在系统调用完成时唤醒它们,为您提供同步API来处理异步调用.
然而,没有确切的方法可以确定哪个goroutine会被一个接一个地唤醒,或者从一个goroutine直接控制到另一个goroutine - 这就是调度程序的工作.
你关注的是Go中解决的问题,你不必担心它 - 代码了!
编辑:
进一步澄清; 你不应该编码来符合(或更好地利用)Go的调度程序的语义 - 而不是相反.可能有一些代码技巧可以让你今天略微提升性能,但是调度程序可以并且将来会在任何Go版本中发生变化 - 使你的代码优化变得毫无用处甚至对你起作用.
Not*_*fer 10
两种机制可以增强您对此的控制:
runtime.Gosched()
- 将控制权交还给调度程序,但当然它对您已经发出的阻止调用没有帮助.
runtime.LockOSThread()
为这个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.
通过 Go 1.1,goroutine 只会控制阻塞调用(系统调用、通道读/写、互斥锁等)。这意味着 goroutine 理论上可以完全占用 CPU,并且不允许调度程序运行。
在 Go 1.2 中,引入了一项更改来解决此问题:
在之前的版本中,永远循环的 goroutine 可能会导致同一线程上的其他 goroutine 挨饿,当 GOMAXPROCS 只提供一个用户线程时,这是一个严重的问题。在 Go 1.2 中,这个问题得到了部分解决:在进入函数时偶尔会调用调度程序。这意味着任何包含(非内联)函数调用的循环都可以被抢占,从而允许其他 goroutine 在同一线程上运行。
(来源:go1.2发行说明)
理论上,goroutines 仍然有可能通过从不调用非内联函数来占用 CPU,但这种情况比从不进行阻塞调用的 goroutine 更为罕见,而这正是 Go 1.2 之前的情况。