为了账号安全,请及时绑定邮箱和手机立即绑定

将产生 goroutines 的 golang 方法

将产生 goroutines 的 golang 方法

Go
繁星淼淼 2021-07-06 13:10:51
据我所知,goroutines 会在其他 goroutines 太忙时阻止它们运行。对我来说,这意味着我的应用程序的性能和响应能力可能取决于我知道哪些库方法将控制其他 goroutines(例如典型的 Read() 和 Write())有什么方法可以让我确切地知道不同的库方法将如何将控制权交给其他 goroutine,即实际上不会阻塞?有什么方法可以实现一个新方法来调用第三方代码(包括像 findnextchangenotification 这样依赖于 waitforsingleobject 或 waitformultipleobjects 的异步 Win32 API)并且在 Go 调度器中表现得“很好”?在这个特定的例子中,系统调用将在完成后发出信号,我需要等到它完成而不用尽所有其他 goroutine。关于如何处理 Go 中的第三方阻塞操作,以便它们不会耗尽其他 goroutines,是否还有另一种“最佳实践”?我假设 Go 运行时可能在后台线程上内部运行某种 IO 循环,以便“挂起”阻塞的 goroutine 操作,直到它们完成 IO。如果确实如此,那么我想能够在此基础上构建新的阻塞操作可能会很有用。
查看完整描述

3 回答

?
慕桂英546537

TA贡献1848条经验 获得超10个赞

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

阅读有关调度程序如何工作的更多信息。

然而,没有确切的方法来确定哪个 goroutine 将被一个接一个地唤醒或将控制权从一个 goroutine 直接交给另一个 goroutine - 这是调度程序的工作。

您关心的是 Go 中已解决的问题,您不必担心 - 代码消失!

编辑:

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


查看完整回答
反对 回复 2021-07-19
?
慕丝7291255

TA贡献1859条经验 获得超6个赞

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


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


runtime.LockOSThread()将一个真正的 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.


查看完整回答
反对 回复 2021-07-19
?
慕沐林林

TA贡献2016条经验 获得超9个赞

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

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

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

从理论上讲,通过从不调用非内联函数,仍然有可能让 goroutines 占用 CPU,但这种情况比从不进行阻塞调用的goroutines 少得多,这是在 Go 1.2 之前得到的。


查看完整回答
反对 回复 2021-07-19
  • 3 回答
  • 0 关注
  • 242 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信