同一结构中的多个互斥体?
Multiple mutexes in same struct?
我有一些关于 Go 的 sync.Mutex
与 struct
一起使用的相关问题。例如,如果我有这个 struct
:
type something struct {
aMux sync.Mutex
a map[string]interface{}
bMux sync.Mutex
b int
}
... 在没有竞争条件的情况下同时锁定 aMux
和访问 a
时锁定 bMux
和访问 b
是否安全?
了解我正在访问指向结构的指针,并使用类似这样的方法同时 lock/unlock 互斥体可能也有帮助:
func (s *something) addA(k string, v interface{}) {
(*s).aMux.Lock()
(*s).a[k] = v
(*s).aMux.Unlock()
}
func (s *something) addB(k string, v interface{}) {
(*s).bMux.Lock()
(*s).b++
(*s).bMux.Unlock()
}
我的假设是这在理论上应该是安全的,因为您已经可以在结构中锁定互斥锁而无需访问它锁定的字段。 但是当像上面那样取消引用 struct
时,Go 是从 struct
复制所有值(使其不安全),还是仅 modify/retrieve 您指定的字段?
我非常希望将互斥量保留在同一个结构中,因为在我的代码中,我在同一个结构中有多个(最多六个)相关字段,我用互斥量分别锁定。 如果在同一个结构(对于相关字段)中有多个互斥体是安全的,但不推荐或不好的做法,为什么?什么是更好的结构?
在一个结构中拥有多个互斥量应该是安全的。请注意不要按值传递结构,因为互斥锁不是引用类型并且复制它们是错误的(有关详细信息,请参阅 this discussion)。
您不需要显式取消引用,Go 会为您完成:
func (s *something) addA(k string, v interface{}) {
s.aMux.Lock()
s.a[k] = v
s.aMux.Unlock()
}
应该也能正常工作(在 Go tour 中)。
虽然我会说这不是很常见的设计。如果可能的话,我更喜欢互斥锁来锁定整个结构。一旦你进行了非常细粒度的锁定,你就必须非常小心,我会先探索其他选项。
- 是的,你的结构中可以有多个互斥体
- 不要使事情过于复杂:您可以使用单个互斥锁来保护对结构中两个元素之一的访问,即任何修改
map
或 int
的操作都可以共享同一个互斥
- 当从其他函数引用您的结构时 - 使用像您的方法一样的指针 - 确保不复制该结构。复制的结构 - 带有互斥量 - 将导致 unpredictable/unsafe 结果
来自 golang mutex docs:
Values containing the types defined in this package (i.e. sync.Mutux) should not be copied.
我有一些关于 Go 的 sync.Mutex
与 struct
一起使用的相关问题。例如,如果我有这个 struct
:
type something struct {
aMux sync.Mutex
a map[string]interface{}
bMux sync.Mutex
b int
}
... 在没有竞争条件的情况下同时锁定 aMux
和访问 a
时锁定 bMux
和访问 b
是否安全?
了解我正在访问指向结构的指针,并使用类似这样的方法同时 lock/unlock 互斥体可能也有帮助:
func (s *something) addA(k string, v interface{}) {
(*s).aMux.Lock()
(*s).a[k] = v
(*s).aMux.Unlock()
}
func (s *something) addB(k string, v interface{}) {
(*s).bMux.Lock()
(*s).b++
(*s).bMux.Unlock()
}
我的假设是这在理论上应该是安全的,因为您已经可以在结构中锁定互斥锁而无需访问它锁定的字段。 但是当像上面那样取消引用 struct
时,Go 是从 struct
复制所有值(使其不安全),还是仅 modify/retrieve 您指定的字段?
我非常希望将互斥量保留在同一个结构中,因为在我的代码中,我在同一个结构中有多个(最多六个)相关字段,我用互斥量分别锁定。 如果在同一个结构(对于相关字段)中有多个互斥体是安全的,但不推荐或不好的做法,为什么?什么是更好的结构?
在一个结构中拥有多个互斥量应该是安全的。请注意不要按值传递结构,因为互斥锁不是引用类型并且复制它们是错误的(有关详细信息,请参阅 this discussion)。
您不需要显式取消引用,Go 会为您完成:
func (s *something) addA(k string, v interface{}) {
s.aMux.Lock()
s.a[k] = v
s.aMux.Unlock()
}
应该也能正常工作(在 Go tour 中)。
虽然我会说这不是很常见的设计。如果可能的话,我更喜欢互斥锁来锁定整个结构。一旦你进行了非常细粒度的锁定,你就必须非常小心,我会先探索其他选项。
- 是的,你的结构中可以有多个互斥体
- 不要使事情过于复杂:您可以使用单个互斥锁来保护对结构中两个元素之一的访问,即任何修改
map
或int
的操作都可以共享同一个互斥 - 当从其他函数引用您的结构时 - 使用像您的方法一样的指针 - 确保不复制该结构。复制的结构 - 带有互斥量 - 将导致 unpredictable/unsafe 结果
来自 golang mutex docs:
Values containing the types defined in this package (i.e. sync.Mutux) should not be copied.