你啥时候在 Go 的 struct 中嵌入互斥锁?

Posted

技术标签:

【中文标题】你啥时候在 Go 的 struct 中嵌入互斥锁?【英文标题】:When do you embed mutex in struct in Go?你什么时候在 Go 的 struct 中嵌入互斥锁? 【发布时间】:2017-12-10 11:51:30 【问题描述】:

注意:我发现标题中的“嵌入”一词是错误的选择,但我会保留它。

我看到很多代码都是这样的:

type A struct 
    mu sync.Mutex
    ...

并像这样使用它:

a := &A

a.mu.Lock()
defer a.mu.Unlock()

a.Something()

比局部互斥还是全局互斥好?

a := &A

var mu sync.Mutex
mu.Lock()
defer mu.Unlock()

a.Something()

我应该什么时候使用前者,还是以后使用?

【问题讨论】:

您的第一个示例不起作用,因为您无法在没有显式接收器的情况下调用 A 上的方法表达式。如果您要询问每个结构实例使用单个互斥锁或单个全局互斥锁;您需要全局互斥锁还是要单独锁定每个实例?这取决于您要完成的工作。 谢谢。我改变了我的代码。 【参考方案1】:

最好让互斥锁靠近它要保护的数据。如果互斥锁应该保护对结构值字段的并发访问,则将互斥锁添加为该结构的字段非常方便,因此其目的很明显。

如果在您的应用中只有一个“实例”A,也可以将互斥锁设为全局变量。

如果你的应用要创建A的多个值,所有这些都需要被保护以防止并发访问(但只能单独地,多个值可能被同时访问),那么显然全局互斥锁是一个不好的选择,它将在任何时间点将并发访问限制为A 的单个值。

将互斥锁作为字段添加到结构中,自然为每个不同的结构值都有一个单独的互斥锁,负责保护单个包装器结构值(或其字段)。 p>

虽然在您的示例中添加互斥锁不是嵌入,但它是一个常规的命名字段。 embedded field declaration 省略了字段名称。

它在较小程度上是众所周知的,但它也很方便,您可以“真正”将互斥锁嵌入到结构中,您可以调用 Lock()Unlock(),就好像它们是结构本身的一部分一样.它看起来像这样:

var hits struct 
    sync.Mutex
    n int


hits.Lock()
hits.n++
hits.Unlock()

(本例取自10 things you (probably) don't know about Go, slide #3。)

【讨论】:

以上是关于你啥时候在 Go 的 struct 中嵌入互斥锁?的主要内容,如果未能解决你的问题,请参考以下文章

同一个结构中有多个互斥锁?

go channel 也是通过共享内存和互斥锁来实现通信的

浅谈go语言中的读写锁和互斥锁

go 互斥锁,读写锁(sync.Mutex,sync.RWMutex)

Go 语言 Channel

Go 语言 Channel