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

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

Global Thread-local Storage feasibility and best Practices in Go

问题

我是一个Golang的初学者,我想在Go中实现类似于Java中通过线程本地存储实现的Mapped Diagnostic Context(MDC)。然而,我发现在Go的线上资源中很难找到关于全局线程本地存储的信息。

我有几个问题:

  • 在Go中是否可以为每个goroutine创建一种类似于全局线程本地存储的机制来存储数据和上下文?
  • 在Go中尝试实现全局线程本地存储是否被认为是一种反模式?
  • 在Go中,是否建议通过实现全局线程本地存储来替换传递上下文的方式?
  • 假设你可以选择,你更倾向于使用传递上下文的方法,还是尝试实现线程本地存储来保存和管理上下文?

我找到了一些相关的参考资料,但我无法得出结论是否要实现它:

英文:

I am a beginner in Golang, and I would like to implement something similar to the Mapped Diagnostic Context (MDC) in Java, which is achieved through thread-local storage, in Go. However, I find it hard to find information about global thread-local storage in Go online.

I have several questions:

  • Is it possible to create a kind of global thread-local storage for each goroutine in Go to store data and context?

  • Is attempting to implement global thread-local storage considered an anti-pattern in Go?

  • Is it recommended to replace the way of passing context by implementing global thread-local storage in Go?

  • Assuming in your choice, would you prefer to use the method of passing context or would you attempt to implement a thread-local storage to save and manage context?

I've found some references to this, but I can't come to a conclusion to decide whether to implement it or not.

答案1

得分: 5

这里有几个问题,通常在尝试在Go语言中模拟其他语言的特性时会出现。

  • Goroutines不是线程。Goroutines没有像线程那样的身份标识。
  • Context用于存储请求范围的状态和数据。它不是线程本地存储的替代品。
  • 如果你认为你需要线程本地存储,那么你可能误用了goroutines。线程本地存储和线程池通常在线程创建成本高昂时使用,因此你只需创建它们一次并重复使用。除非goroutine的初始化成本很高,否则在Go中不要这样做。对于大多数情况,只需创建一个新的goroutine并让它运行到完成。
  • 如果你仍然认为你需要线程本地存储,可以考虑使用闭包:
func f() {
   var i int
   go func() {
      // 在这里,将i用作线程本地存储
   }()
}
  • 如果闭包不适用,可以通过传递一个结构体来实现线程本地存储:
func f() {
  go func() {
     var t threadLocalData
     ...
     g(t)
     ...
  }()
}
英文:

There are several issues here, which usually happen when you try to emulate features of other languages in Go.

  • Goroutines are not threads. Goroutines do not have identities like threads do.
  • Context is to store request-scope state and data. It is not a replacement for thread-local storage.
  • If you think you need thread-local storage, then you might be misusing goroutines. Thread-local storage and thread pools are usually used when thread creation is costly, so you create them once and reuse them. Do not do that in Go unless goroutine initialization is costly. For most cases, just create a new goroutine and let it run to completion.
  • If you still think you need thread local storage, consider closures:
func f() {
   var i int
   go func() {
      // Here, use i as thread-local storage
   }()
}
  • If closures do not work, pass a struct around for thread-local storage
func f() {
  go func() {
     var t threadLocalData
     ...
     g(t)
     ...
  }{}
}

huangapple
  • 本文由 发表于 2023年6月6日 13:15:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/76411605.html
匿名

发表评论

匿名网友

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

确定