【发布时间】:2017-02-16 04:20:25
【问题描述】:
据我所知,Go 运行时调度程序通过不断地将 Go 例程分配给 OS 线程来管理一些 OS 线程(可能超过 GOMAXPROCS?)和 Go 例程。
所以这基本上意味着 Go 例程的执行,包括 main goroutine ,由 go scheduler 和 OS 的线程调度共同管理。
现在这是我的问题..
如果我在 goroutine 开始时调用
runtime.LockOSThread(),goroutine 的执行是否完全由操作系统的线程调度管理?非 Go 线程的执行是否也完全由操作系统的线程调度管理?换句话说,如果我通过
CreateThread函数(Windows)创建了一个非Go线程,那么管理非Go线程的执行是否超出了Go的运行时调度程序的范围?如果我在那个非 Go 线程中使用
go func()启动另一个 goroutine 会怎样?如何管理非 Go 线程和 goroutine 的执行?-
目前,我正在用 Golang 编写一个程序,它在 go 程序的
main()函数中运行一个 Windows 消息循环。 大多数情况下它运行良好,但有时消息循环被阻塞并在几秒钟后恢复,然后大量旧消息被抽出。 (我的另一个问题:Windows Message Loop is getting blocked and resumed intermittently (golang))我不知道为什么会发生,所以我怀疑主 goroutine 的 OS 线程切换是由 go scheduler 引起的。所以我在
main()函数的开头添加了runtime.LockOSThread(),以确保windows消息循环总是在同一个线程中运行。 但是问题还是出现了!我仍然不知道它为什么会发生,但我怀疑这是因为 Go 调度程序,因为用 Python 3.4 编写的相同逻辑没有出现这样的问题。
所以我现在正在尝试通过调用
CreateThread(...)函数创建一个新的 Windows 线程(非 Go 线程),并在该线程中运行 Windows 消息循环。但我很好奇,从 Go 运行时调度程序的角度来看,这种方法与在运行 windows 消息循环的主 goroutine 中调用
runtime.LockOSThread()是否不同。所以我的问题是,'如果我使用
CreateThread(...)函数创建一个新的非 Go 线程并在该线程中运行 windows 消息循环,那么该线程的执行是否不受 Go 运行时调度程序的影响?'
任何帮助或想法将不胜感激。 谢谢。
【问题讨论】:
-
我相当肯定,如果没有运行时的支持,您不能安全地使用新的操作系统线程,无论是让运行时产生线程还是使用 cgo。你不能比 LockOSThread 更好地将 goroutine 固定到线程。我认为您需要了解您的应用在被阻止时在做什么。
-
@JimB 感谢您的评论。我很难弄清楚我的应用程序在被阻止时正在做什么。因为这个问题是随机发生的。你能给我任何建议或工具来弄清楚我的程序在被阻塞时在做什么吗?谢谢
-
检查包
runtime文档,看看您是否可以使用GODEBUG环境变量设置之一来查看您获得的暂停是否与GC 暂停相对应。你也可以试试这个:使用一些 C 代码中的CreateThread()创建一个 Go 不知道的线程,并在那里创建你的窗口和泵消息。这里的内存管理会有点困难,但SendMessageW()可用于跨线程发送消息,因此从 Go 到 C 的基本通信将起作用。 (在开始 libui 重写之前,我打算用我的包 ui 执行此操作。我可能仍会这样做。) -
您没有继续处理您之前的问题并回复
runtime.LockOSThread()没有帮助您,而是发布了一个包含一般性和不清楚的问题的新问题,然后继续讨论您之前的问题的问题?这就是上一篇文章的目的!至于您对使用工具的问题:(1)一旦您被阻止,请附加一个调试器; (2)一旦你被阻止就生成一个转储; (3) 使用 Process Explorer / Process Hacker 查看你被阻塞时线程在做什么; (4) 在分析器下运行你的程序; (5) ...