golang方法将产生goroutines

时间:2014-01-13 21:50:58

标签: go goroutine

据我所知,如果他们太忙,goroutines会阻止其他goroutines运行。对我来说,这意味着我的应用程序的性能和响应性可能取决于我知道哪些库方法将控制其他goroutine(例如通常是Read()和Write())

有什么方法可以确切地知道不同的库方法如何控制其他goroutine,即实际上不会阻塞?

有没有办法可以实现一个调用第三方代码的新方法(包括依赖于waitforsingleobject或waitformultipleobjects的异步Win32 API,如findnextchangenotification),并且对Go调度程序表现“不错”?在这个特定的例子中,系统调用将在完成后发出信号,我需要等到它完成后不再耗尽所有其他的goroutines。

对于如何在Go中处理第三方阻止操作以便他们不会耗尽其他goroutines,是否还有另一种“最佳实践”?

我假设Go运行时可能在后台线程上内部运行某种IO循环,以便“暂停”阻止goroutine操作,直到完成IO。如果情况确实如此,那么我认为能够在此基础上进行新的阻塞操作可能是有用的。

3 个答案:

答案 0 :(得分:13)

Go的调度程序将挂起等待系统调用的goroutine,并在系统调用完成时将其唤醒,为您提供同步API来处理异步调用。

Read more关于调度程序的工作原理。

然而,没有确切的方法可以确定哪个goroutine会被一个接一个地唤醒,或者从一个goroutine直接控制到另一个goroutine - 这就是调度程序的工作。

您的关注是Go中已解决的问题,您无需担心 - 代码离开!

修改

进一步澄清;你不应该编码来符合(或更好地利用)Go的调度程序的语义 - 而不是相反。可能有一些代码技巧可以让你今天略微提升性能,但是调度程序可以并且将来会在任何Go版本中发生变化 - 使你的代码优化变得无用甚至对你不利。

答案 1 :(得分:10)

两种机制可以增强您对此的控制:

  1. runtime.Gosched() - 将控制权交还给调度程序,但当然它对您已经发出的阻止调用无效。

  2. runtime.LockOSThread()将一个真正的操作系统线程专门用于此goroutine而不是其他,这意味着调度程序中的竞争将会减少。来自文档:

  3. 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.

答案 2 :(得分:4)

通过Go 1.1,goroutines只会控制阻塞调用(系统调用,通道读/写,互斥锁等)。这意味着goroutines理论上可以完全占用CPU,并且不允许调度程序运行。

在Go 1.2中,引入了一项修改来解决此问题:

  

在以前的版本中,永远循环的goroutine可能会在同一个线程上淘汰其他goroutine,这是GOMAXPROCS只提供一个用户线程时的一个严重问题。在Go 1.2中,部分解决了这个问题:在进入函数时偶尔会调用调度程序。这意味着任何包含(非内联)函数调用的循环都可以被抢占,允许其他goroutine在同一个线程上运行。

(来源:go1.2 release notes

理论上,仍然可以通过从不调用非内联函数来让goroutine占用CPU,但是这种情况比从未进行阻塞调用的goroutine要少得多,这就是让你在Go 1.2之前。