【问题标题】:Does runtime.LockOSThread allow child goroutines to run in same OS thread?runtime.LockOSThread 是否允许子 goroutines 在同一个操作系统线程中运行?
【发布时间】:2015-06-05 02:42:52
【问题描述】:

我知道在 Go 中,runtime.LockOSThread() 会将一个 goroutine 绑定到一个 OS 线程,并且不允许其他 goroutine 在该线程中执行。 对于子 goroutines 也是如此吗?

例如:

runtime.LockOSThread()
go func() {
    go func() {
        // Do something
    }()
    // Do something
}()

这两个 goroutine 是在一个独占的操作系统线程中执行还是只在第一个线程中执行?

【问题讨论】:

标签: go


【解决方案1】:

The documentation for runtime.LockOSThread 说:

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

(强调我的)

这意味着如果 Go 的某个实现按照您的要求进行,那将是错误的。

澄清一下:如果一个 goroutine 保留了一个线程,而另一个 goroutine 在同一线程上执行;那就错了。

【讨论】:

  • 我使用的是 1.4 版。我已经多次运行示例(现在已删除)并且与我的结论一致。如果实现与文档不一致,我同意。但是,如果您不能在该线程中生成更多受控的 goroutine,我认为将单个 go 例程锁定到一个 OS 线程没有任何好处。
  • 也许runtime.NumCPU() 在您的系统上返回 1?无论如何你应该报告这个错误,包括重现。
  • 我正在使用runtime.GOMAXPROCS(runtime.NumCPU())。我会报告这个错误。但我相信错误出现在文档中,因为如果您不允许内部并发,我无法理解将 goroutine 锁定到 OS 线程的好处。即使它的用法在文档中也不清楚,并且可能会被误解。它将下一个创建的 goroutine 锁定到 OS 线程还是当前线程?一点都不清楚。
  • 调用runtime.LockOSThread() 的goroutine 是一个固定在线程上的goroutine。如果您从那里使用go ...,则生成的goroutine应该在同一个线程上执行。
  • 重要的是要记住runtime.LockOSThread() 不会阻止其他线程从运行 goroutine 的线程的上下文中生成,这意味着其他 goroutine 可以在共享某些特定的上下文中运行特定于线程的数据,例如命名空间、uid 和 gid。欲了解更多信息,请参阅:github.com/golang/go/issues/1435
【解决方案2】:

我们可以使用 pthread.h 的pthread_self 来检查它:

package main

// #include <pthread.h>
import "C"
import (
    "fmt"
    "runtime"
)

func main() {
    runtime.GOMAXPROCS(runtime.NumCPU())
    ch1 := make(chan bool)
    ch2 := make(chan bool)
    fmt.Println("main", C.pthread_self())
    go func() {
        runtime.LockOSThread()
        fmt.Println("locked", C.pthread_self())
        go func() {
            fmt.Println("locked child", C.pthread_self())
            ch1 <- true
        }()
        ch2 <- true
    }()
    <-ch1
    <-ch2
}

在我的机器上,它会打印出类似这样的内容,mainlocked 总是有时相同,但有时不同:

main 139711253194560
locked 139711219787520
locked child 139711236572928

编辑我忘记了 GOMAXPROCS。补充,现在结果不一样了。

【讨论】:

  • 谢谢。我试验了你的例子,在第一次去之前把锁放在上面,效果很好。您可以将该示例添加到您的答案中,或者允许我复制您的示例来回答我自己的问题。
  • @joaonrb 起初我忘了设置 GOMAXPROCS。我现在已经编辑过了。
  • 原来我在代码后期使用了 runtime.LockOSThread()。我用你的例子来解释我的问题的解决方案。谢谢。
猜你喜欢
  • 2015-07-16
  • 1970-01-01
  • 1970-01-01
  • 2018-01-29
  • 1970-01-01
  • 2018-10-16
  • 2016-02-23
  • 2021-10-24
  • 2013-02-09
相关资源
最近更新 更多