Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/go/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
将产生goroutine的golang方法_Go_Goroutine - Fatal编程技术网

将产生goroutine的golang方法

将产生goroutine的golang方法,go,goroutine,Go,Goroutine,据我所知,如果其他goroutine太忙,goroutine将阻止它们运行。对我来说,这意味着我的应用程序的性能和响应性可能取决于我是否知道哪些库方法将控制其他goroutine(例如,通常是Read()和Write()) 我有没有办法确切地知道不同的库方法是如何控制其他goroutine的,即不实际阻塞的 有没有办法实现一个调用第三方代码的新方法(包括一个异步Win32 API,比如FindTextChangeNotification,它依赖于waitforsingleobject或waitf

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

我有没有办法确切地知道不同的库方法是如何控制其他goroutine的,即不实际阻塞的

有没有办法实现一个调用第三方代码的新方法(包括一个异步Win32 API,比如FindTextChangeNotification,它依赖于waitforsingleobject或waitformultipleobjects)并在Go调度程序中表现“良好”?在这个特定的示例中,系统调用一旦完成就会发出信号,我需要等待它完成,而不会耗尽所有其他goroutine

对于如何处理Go中的第三方阻塞操作,以避免耗尽其他Goroutine,是否还有其他“最佳实践”


我假设Go运行时可能在后台线程内部运行某种IO循环,以便“挂起”阻塞goroutine操作,直到它们完成IO。如果确实是这样的话,那么我想能够在此基础上构建新的阻塞操作可能会很有用。

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

关于调度程序如何工作

然而,没有确切的方法来确定哪个goroutine将被一个接一个地唤醒,或者将控制权从一个goroutine直接转移到另一个goroutine,这是调度器的工作

在Go中,您的问题已经解决,您不必担心它—代码将被删除

编辑:


进一步澄清;您不应该编写符合(或更好地利用)Go的调度器语义的代码——相反。今天可能有一些代码技巧可以让您的性能略有提高,但调度器可以而且将在将来的任何Go版本中更改—使您的代码优化毫无用处,甚至对您不利。

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

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

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

(来源:)


从理论上讲,通过从不调用非内联函数,goroutines仍然有可能占用CPU,但这种情况比goroutines更为罕见,因为goroutines从不进行阻塞调用,这是Go 1.2之前的原因。

有两种机制可以增强您对这一点的控制:

  • runtime.Gosched()
    -将控制权返回给调度程序,但当然它对您已经发出的阻塞调用没有帮助

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

  • 
    LockOSThread将调用goroutine连接到其当前操作系统线程。在调用goroutine退出或调用UnlockOSThread之前,它将始终在该线程中执行,其他goroutine无法执行。
    

    谢谢您的回复。虽然很有趣,并且部分回答了我的问题,但我仍然想知道如何使我的自定义阻塞方法以最好的方式与调度程序配合使用?如果计划程序使用某种内部事件通知循环,则也可以将其用于自定义库?如果要强制计划程序运行,可以调用
    runtime.Gosched()
    。但除非你真的注意到问题,否则这可能是不值得的。如果你使用Go 1.2,你不应该有任何问题,除非你的代码循环而不进行任何函数调用。每个函数调用都给调度器一个跳入并“抢占”当前运行的goroutine的机会。编译器和运行时将确定何时真正抓住这个机会,但您应该假设它擅长明智地做出决策。谢谢您的回复。我关心的不是如何让它发挥作用,而是如何使它尽可能好。在我看来,一定存在某种内部事件通知循环,而将其用于我自己的阻塞调用似乎是确保良好性能和调度的最佳方式?我已修改了我的答案。不过,这很有趣,重用现有的事件循环不是更有效吗?取决于此类“阻塞”goroutine的数量。从Go 1.2开始,我认为您不必担心任何问题,因为goroutines即使在不阻塞IO的情况下也会产生执行,并且新的goroutines会抢占调度程序(不确定这是否是正确的术语,但您明白我的意思)。我个人把这些东西留给go调度员,除非您正在调用外部C库。调用外部C库实际上是我最初问题的用例。那么,如果您不打算对许多Goroutine执行此操作,那么锁定操作系统线程可能不是一个坏主意。挑剔:您将
    Gosched
    Goshced
    拼写错误。除此之外,你的回答帮助了我。谢谢