小编典典

什么时候将互斥锁嵌入到struct中?

go

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

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

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()

我应该什么时候使用前一个或更晚的版本?


阅读 197

收藏
2020-07-02

共1个答案

小编典典

保持互斥锁接近要保护的数据是一种好习惯。如果互斥锁应该保护对结构值字段的并发访问,则将互斥锁添加为该结构的字段非常方便,因此其目的显而易见。

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

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

将互斥量作为字段添加到结构中,您 自然 会为每个不同的结构值拥有一个单独的互斥体,负责保护包含该结构值(或其字段)的单个互斥量。

尽管在您的示例中未添加互斥锁,但它是一个常规的命名字段。在嵌入式领域声明省略字段名。

它的知名度和使用程度较小,但也很方便,您可以“真正地”将互斥体嵌入结构中,并且可以进行调用Lock()Unlock()就好像它们将成为结构本身的一部分一样。看起来像这样:

var hits struct {
    sync.Mutex
    n int
}

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

(此示例摘自您(可能)对Go不了解的10件事,幻灯片#3。)

2020-07-02