Go中全局线程本地存储的可行性和最佳实践

Cha*_*nds 2 multithreading go mdc goroutine thread-local-storage

我是Golang的初学者,我想在Go中实现类似于Java中的映射诊断上下文(MDC)的东西,这是通过线程本地存储来实现的。但是,我发现很难在网上找到有关 Go 中全局线程本地存储的信息。

我有几个问题:

  • 是否可以为Go中的每个goroutine创建一种全局线程本地存储来存储数据和上下文?

  • 尝试实现全局线程局部存储是否被认为是 Go 中的反模式?

  • 是否建议通过在 Go 中实现全局线程本地存储来替代传递上下文的方式?

  • 假设您的选择是,您更喜欢使用传递上下文的方法,还是尝试实现线程本地存储来保存和管理上下文?

我找到了一些对此的参考,但我无法得出结论来决定是否实施它。

Bur*_*dar 5

这里有几个问题,当您尝试在 Go 中模拟其他语言的功能时通常会发生这些问题。

  • Goroutine 不是线程。Goroutines 不像线程那样有身份。
  • 上下文用于存储请求范围的状态和数据。它不是线程本地存储的替代品。
  • 如果您认为需要线程本地存储,那么您可能会误用 goroutine。当线程创建成本高昂时,通常会使用线程本地存储和线程池,因此您可以创建一次并重用它们。不要在 Go 中这样做,除非 goroutine 初始化成本很高。对于大多数情况,只需创建一个新的 goroutine 并让它运行完成即可。
  • 如果您仍然认为需要线程本地存储,请考虑闭包:
func f() {
   var i int
   go func() {
      // Here, use i as thread-local storage
   }()
}
Run Code Online (Sandbox Code Playgroud)
  • 如果闭包不起作用,请传递一个结构以进行线程本地存储
func f() {
  go func() {
     var t threadLocalData
     ...
     g(t)
     ...
  }{}
}
Run Code Online (Sandbox Code Playgroud)