你什么时候在Go中嵌入mutex?

kim*_*bin 4 embed struct mutex go

注意:我发现标题中的"嵌入"这个词是不好的选择,但我会保留它.

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

type A struct {
    mu sync.Mutex
    ...
}
Run Code Online (Sandbox Code Playgroud)

并像这样使用它:

a := &A{}

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

a.Something()
Run Code Online (Sandbox Code Playgroud)

它是否优于本地互斥或全局互斥?

a := &A{}

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

a.Something()
Run Code Online (Sandbox Code Playgroud)

我什么时候应该使用前者或以后?

icz*_*cza 23

保持互斥锁接近预定要保护的数据是一种好习惯.如果互斥锁应该保护对结构值字段的并发访问,那么将互斥锁添加为该结构的字段非常方便,因此其目的很明显.

如果在你的应用程序中只有一个"实例" A,那么将互斥锁变为全局变量也没关系.

如果你的应用程序要创建多个值A,所有这些都需要保护免受并发访问(但是只能单独地,多个值可以同时访问),那么显然全局互斥是一个糟糕的选择,它会限制并发访问A任何时间点的单一值.

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

虽然在示例中添加互斥锁不是嵌入,但它是一个常规的命名字段.在嵌入式领域声明省略字段名.

它在较小程度上是已知和使用的,但是你可以"真正"在结构中嵌入一个互斥体也很方便,你可以调用它Lock(),Unlock()就像它们将成为结构本身的一部分一样.它看起来像这样:

var hits struct {
    sync.Mutex
    n int
}

hits.Lock()
hits.n++
hits.Unlock()
Run Code Online (Sandbox Code Playgroud)

(这个例子取自你(可能)不知道Go,幻灯片#3的10件事.)