据我所知,如果goroutines太忙,它们会阻止其他goroutine运行。对我来说,这意味着我的应用程序的性能和响应性可能取决于我知道哪些库方法会将控制权交给其他goroutine(例如,通常是Read()和Write())
我有没有办法确切地知道不同的库方法将如何将控制权交给其他goroutine,即不是真正的块?
有没有办法实现一个新的方法,调用第三方代码(包括像findnextchangenotification这样的异步Win32 API,它依赖于waitforsingleobject或waitforsingleobject),并在Go调度程序中表现得“很好”?在这个特定的例子中,syscall将在完成后发出信号,我需要等到它完成,而不会耗尽所有其他goroutines。
对于如何处理Go中的第三方阻塞操作,是否还有另一种“最佳实践”,以便它们不会耗尽其他goroutine?
我假设Go运行时可能在后台线程上内部运行某种IO循环,以便“暂停”阻塞goroutine操作,直到它们完成IO为止。如果确实是这样,那么我想能够在此基础上构建新的阻塞操作可能会很有用。
发布于 2014-01-14 06:17:48
Go的调度程序将暂停等待syscall的goroutines,并在syscall完成时唤醒它们,为您提供一个同步API来处理异步调用。
有关调度程序如何工作的Read more。
然而,没有确切的方法来确定哪个goroutine将在另一个goroutine之后被唤醒,或者将控制权从一个goroutine直接移交给另一个goroutine--这是调度器的工作。
在Go中,你关心的是一个已经解决的问题,你不必担心它--把代码移开!
编辑:
为了进一步澄清,您不应该编写代码以符合(或更好地利用)Go的调度器的语义--相反。今天可能有一些代码技巧可以让您的性能略有提高,但在未来的任何Go版本中,调度器都会发生变化--使您的代码优化变得无用,甚至对您不利。
发布于 2014-01-14 17:54:14
有两种机制可以增强您对此的控制:
runtime.Gosched() -将控制权交还给调度器,但它当然不会对阻塞调用有所帮助,因为你已经将一个真正的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.
发布于 2014-01-14 12:56:36
通过Go 1.1,goroutines将只在阻塞调用(syscall,通道读/写,互斥锁等)上产生控制。这意味着goroutines在理论上可以完全占用CPU,并且不允许调度器运行。
在Go 1.2中,引入了一个更改来解决这个问题:
在以前的版本中,永远循环的goroutine可能会饿死同一线程上的其他goroutine,当GOMAXPROCS只提供一个用户线程时,这是一个严重的问题。在Go 1.2中,这部分解决了这个问题:调度器偶尔会在进入函数时被调用。这意味着任何包含(非内联)函数调用的循环都可以被抢占,从而允许其他goroutines在同一线程上运行。
(来源:go1.2 release notes)
从理论上讲,仍然可以让goroutines通过从不调用非内联函数来占用CPU,但这种情况比从不进行阻塞调用的goroutine要少得多,这是在Go 1.2之前获得的。
https://stackoverflow.com/questions/21102078
复制相似问题