你什么时候在 Go 的结构中嵌入互斥量?
When do you embed mutex in struct in Go?
注意:我发现标题中的 'embed' 这个词是错误的选择,但我会保留它。
我看到很多代码都是这样的:
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
的一个“实例”,也可以将互斥体设为全局变量。
如果您的应用程序要创建 A
的多个值,所有这些值都需要防止并发访问(但只是单独地,多个值可以同时访问),那么显然全局互斥锁是糟糕的选择,它会限制在任何时间点对 A
的单个值的并发访问。
将互斥锁作为字段添加到结构中,您将自然地为每个不同的结构值拥有一个单独的互斥锁,负责保护单个包装器结构值(或其字段)。
虽然在您的示例中添加互斥锁不是嵌入,但它是一个常规的命名字段。 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。)
注意:我发现标题中的 'embed' 这个词是错误的选择,但我会保留它。
我看到很多代码都是这样的:
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
的一个“实例”,也可以将互斥体设为全局变量。
如果您的应用程序要创建 A
的多个值,所有这些值都需要防止并发访问(但只是单独地,多个值可以同时访问),那么显然全局互斥锁是糟糕的选择,它会限制在任何时间点对 A
的单个值的并发访问。
将互斥锁作为字段添加到结构中,您将自然地为每个不同的结构值拥有一个单独的互斥锁,负责保护单个包装器结构值(或其字段)。
虽然在您的示例中添加互斥锁不是嵌入,但它是一个常规的命名字段。 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。)