简体   繁体   English

golang方法将产生goroutines

[英]golang methods that will yield goroutines

As far as I can understand, goroutines will block other goroutines from running if they are too busy. 据我所知,如果他们太忙,goroutines会阻止其他goroutines运行。 For me, this means that the performance and responsiveness of my application will probably depend on me knowing which library methods that will yield control over to other goroutines (eg typically Read() and Write()) 对我来说,这意味着我的应用程序的性能和响应性可能取决于我知道哪些库方法将控制其他goroutine(例如通常是Read()和Write())

Is there any way I can know exactly how different library methods will yield control over to other goroutines ie not actually block? 有什么方法我可以确切地知道不同的库方法将如何控制其他goroutine,即实际上没有阻止?

Is there any way I can implement a new method that calls third party code (including a async Win32 API like findnextchangenotification that relies on waitforsingleobject or waitformultipleobjects) and behaves "nice" with the Go scheduler? 有没有办法可以实现一个调用第三方代码的新方法(包括依赖于waitforsingleobject或waitformultipleobjects的异步Win32 API,如findnextchangenotification),并且对Go调度程序表现“不错”? In this particular example, the syscall will signal once finished and I need to wait until it is finished withot exhausting all other goroutines. 在这个特定的例子中,系统调用将在完成后发出信号,我需要等到它完成后不会耗尽所有其他goroutine。

Is there perhaps another "best practice" for how to deal with third party blocking operations in Go so that they don't exhaust the other goroutines? 是否还有另一个“最佳实践”,如何处理Go中的第三方阻止操作,以便它们不会耗尽其他goroutines?

I assume that the Go runtime perhaps have some sort of IO-loop internally running on a background thread in order to "suspend" blocking goroutine operations until they finished with IO. 我假设Go运行时可能在后台线程上内部运行某种IO循环,以便“暂停”阻止goroutine操作,直到它们完成IO。 If this is indeed the case, then I guess it could be useful to be able to build upon this for new blocking operations. 如果确实如此,那么我认为能够在此基础上构建新的阻塞操作可能会很有用。

Go's scheduler will suspend goroutines that are waiting for a syscall and wake them when the syscall has completed, giving you a synchronous API to deal with asynchronous calls. Go的调度程序将暂停正在等待系统调用的goroutine,并在系统调用完成时唤醒它们,为您提供同步API来处理异步调用。

Read more about how the scheduler works. 阅读有关调度程序如何工作的更多信息。

There is, however - no exact way of determining which goroutine will be awoken after another or yielding control from one goroutine directly to another - that's the scheduler's job. 然而,没有确切的方法可以确定哪个goroutine会被一个接一个地唤醒,或者从一个goroutine直接控制到另一个goroutine - 这就是调度程序的工作。

Your concern is a solved problem in Go and you don't have to worry about it - code away! 你关注的是Go中解决的问题,你不必担心它 - 代码了!

Edit: 编辑:

To further clarify; 进一步澄清; you are not supposed to code to conform to (or make better use of) Go's scheduler's semantics -- rather the other way around. 你不应该编码来符合(或更好地利用)Go的调度程序的语义 - 而不是相反。 There might be some code-tricks that can get you slight performance increase today but the scheduler can and will change in any future Go release -- making your code optimizations useless or even work against you. 可能有一些代码技巧可以让你今天略微提升性能,但是调度程序可以并且将来会在任何Go版本中发生变化 - 使你的代码优化变得毫无用处甚至对你起作用。

Two mechanisms can enhance your control over this: 两种机制可以增强您对此的控制:

  1. runtime.Gosched() - yields control back to the scheduler, but of course it won't help with a blocking call you've already issued. runtime.Gosched() - 将控制权交还给调度程序,但当然它对你已经发出的阻塞调用没有帮助。

  2. runtime.LockOSThread() dedicates a real OS thread to this goroutine and no other, meaning there will be less competition in the scheduler. runtime.LockOSThread()将一个真实的OS线程专用于此goroutine而不是其他,这意味着调度程序中的竞争会更少。 from the docs: 来自文档:

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.

Through Go 1.1, goroutines would only yield control on blocking calls (syscalls, channel reads/writes, mutex locks, etc). 通过Go 1.1,goroutines只会控制阻塞调用(系统调用,通道读/写,互斥锁等)。 This meant that goroutines could in theory completely hog the CPU, and not allow the scheduler to run. 这意味着goroutines理论上可以完全占用CPU,并且不允许调度程序运行。

In Go 1.2, a change was introduced to fix this: 在Go 1.2中,引入了一个更改以解决此问题:

In prior releases, a goroutine that was looping forever could starve out other goroutines on the same thread, a serious problem when GOMAXPROCS provided only one user thread. 在以前的版本中,永远循环的goroutine可能会在同一个线程上饿死其他goroutine,这是GOMAXPROCS只提供一个用户线程时的一个严重问题。 In Go 1.2, this is partially addressed: The scheduler is invoked occasionally upon entry to a function. 在Go 1.2中,部分解决了这个问题:在进入函数时偶尔会调用调度程序。 This means that any loop that includes a (non-inlined) function call can be pre-empted, allowing other goroutines to run on the same thread. 这意味着任何包含(非内联)函数调用的循环都可以被抢占,允许其他goroutine在同一个线程上运行。

(source: go1.2 release notes ) (来源: go1.2发行说明

In theory, it's still possible to have goroutines hog the CPU by never calling a non-inlined function, but such cases are much more rare than goroutines which never make blocking calls, which is what would get you prior to Go 1.2. 理论上,仍然可以通过从不调用非内联函数来使goroutine占用CPU,但是这种情况比从未进行阻塞调用的goroutine要少得多,这就是Go 1.2之前的情况。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM