Go调度器是否也管理在运行时创建的非Go线程?

huangapple go评论116阅读模式
英文:

Does Go scheduler also manages non-Go Thread created in runtime?

问题

据我所知,Go运行时调度器通过将Go例程连续分配给操作系统线程来管理一些数量的操作系统线程(可能多于GOMAXPROCS)和Go例程。

因此,这基本上意味着包括主goroutine在内的Go例程的执行由Go调度器和操作系统的线程调度共同管理。

现在我有几个问题:

  1. 如果我在goroutine的开头调用runtime.LockOSThread(),那么goroutine的执行是否完全由操作系统的线程调度管理?

  2. 非Go线程的执行是否也完全由操作系统的线程调度管理?换句话说,如果我通过CreateThread函数(Windows)创建一个非Go线程,那么管理非Go线程的执行是否超出了Go运行时调度器的范围?

  3. 如果我在那个非Go线程中使用go func()启动另一个goroutine,那么如何管理那个非Go线程和goroutine的执行?

  4. 目前,我正在使用Golang编写一个程序,在go程序的main()函数中运行一个Windows消息循环。大部分时间它都工作得很好,但有时消息循环会被阻塞,几秒钟后恢复,并且会传递大量的旧消息。(我的另一个问题:Windows消息循环间歇性阻塞和恢复(golang)

我不知道为什么会发生这种情况,所以我怀疑是主goroutine通过go调度器进行了操作系统线程切换。因此,我在main()函数的开头添加了runtime.LockOSThread(),以确保Windows消息循环始终在同一个线程中运行。然而,问题仍然存在!

我仍然不知道为什么会发生这种情况,但我怀疑这是由于Go调度器的原因,因为在Python 3.4中编写的相同逻辑没有出现这样的问题。

所以我现在尝试的是通过调用CreateThread(...)函数创建一个新的Windows线程(非Go线程),并在该线程中运行Windows消息循环。

但我很好奇这种方法是否与在主goroutine中调用runtime.LockOSThread()来运行Windows消息循环在Go运行时调度器的角度有所不同。

所以我的问题是,'如果我使用CreateThread(...)函数创建一个新的非Go线程,并在该线程中运行Windows消息循环,那么该线程的执行是否不受Go运行时调度器的影响?'

非常感谢任何帮助或想法。
谢谢。

英文:

As far as I know, Go runtime scheduler manages some number of OS Threads(probably more than GOMAXPROCS?) and Go routines by assigning Go routines to OS Threads continuously.

So this basically means that the execution of Go routines, including main goroutine , are managed by both of go scheduler and OS' thread scheudling.

Now here's my questions..

  1. Does the execution of goroutine fully managed by OS' thread scheduling if I call runtime.LockOSThread() at the start of that goroutine?

  2. Does the execution of non-Go thread also fully managed by OS' thread scheduling? In other words, if I create a non-Go Thread by CreateThread function (Windows), then the management non-Go Thread's execution is out of scope of Go's runtime scheduler?

  3. What if I launch another goroutine with go func() in that non-Go Thread? How that non-Go Thread and goroutine's execution is managed?

  4. Currently, I'm writing a program in Golang which runs a windows message loop in main() function of go program.
    Most of the time it worked well, but sometimes the message loop get blocked and resumed after few seconds and then large amount of old messages get pumped.
    (My another question: Windows Message Loop is getting blocked and resumed intermittently (golang))

I had no idea why it occurs, so I suspected main goroutine's OS Thread switch by go scheduler. So I added runtime.LockOSThread() at the start of main() function to ensure windows message loop always run in the same thread.
However, the problem still occured!

I still have no idea why it occurs, but I'm suspecting this is because of Go scheduler because the same logic written in Python 3.4 didn't make any problems like this.

So what I'm trying now is creating a new Windows Thread (non-Go Thread) by calling CreateThread(...) function, and running windows message loop in that thread.

But I'm curious that whether this approach is different with calling runtime.LockOSThread() in main goroutine running windows message loop from Go runtime scheduler's perspective.

So my question is, 'If I create a new non-Go Thread with CreateThread(...) function and run windows message loop in that thread, then does execution of that thread not affected by Go's runtime scheduler?'

Any helps or ideas will be greatly appreciated.
Thanks.

答案1

得分: 1

如果你使用CreateThread()例程来运行一个新的操作系统线程,Go的调度器将不会触及该线程。然而,你将需要实现一种方法让该线程与Goroutine进行通信。例如,你不能直接从由CreateThread()创建的线程中调用Go方法。相反,你将需要使用一些基于C的系统来轮询Goroutine中的事件。

另外,如果你想从主操作系统线程中运行循环,你应该在init()函数中调用LockOSThread(),而不是在main()函数中。参见https://github.com/golang/go/wiki/LockOSThread

func init() {
    runtime.LockOSThread();
}
func main() {
    // 在这里运行循环。
}
英文:

If you run a new OS thread using the CreateThread() routine, Go's scheduler will not touch the thread. However, you will then have to implement a way for that thread to communicate with Goroutines. You can't, for instance, call a Go method directly from the thread created by CreateThread(). Instead, you will have to use some C-based system to poll events from a Goroutine.

As an aside, if you want to run the loop from the main OS thread, you should call LockOSThread() in init() rather than in main(). See https://github.com/golang/go/wiki/LockOSThread:

func init() {
    runtime.LockOSThread();
}
func main() {
    // Run loop here.
}

huangapple
  • 本文由 发表于 2017年2月16日 12:20:25
  • 转载请务必保留本文链接:https://go.coder-hub.com/42264882.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定