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

时间:2019-02-14 00:54:13

标签: go struct concurrency mutex

我有一些与sync.Mutex一起使用的Go struct相关的问题。例如,如果我要使用这个struct

type something struct {
    aMux sync.Mutex
    a    map[string]interface{}

    bMux sync.Mutex
    b    int
}

... 在无竞争条件的情况下锁定bMux和访问b并同时锁定aMux和访问a是否安全?

了解我正在访问结构的指针并使用类似方法同时锁定/解锁互斥锁可能也很有帮助:

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中的所有值(使其不安全)还是仅修改/检索您指定的字段?

我非常想将互斥锁保持在相同的结构中,因为在我的代码中,我在同一个结构中使用互斥锁分别锁定了多个(最多六个)相关字段。 如果在同一结构中(对于相关字段)具有多个互斥对象是安全的,但是不建议这样做或不建议这样做,为什么?哪种结构更好?

2 个答案:

答案 0 :(得分:2)

在单个结构中具有多个互斥对象应该是安全的。请注意不要通过值传递结构,因为互斥体不是引用类型,并且复制它们是错误的(有关更多详细信息,请参见this discussion)。

您不需要显式取消引用,Go会为您完成:

Cookie

应该也能正常工作(在Go tour中)。

我会说这不是很平常的设计。如果可能,我希望互斥锁锁定整个结构。一旦执行了非常精细的锁定,就必须非常小心,我将首先探讨其他选项。

答案 1 :(得分:1)

  • 是的,您的结构中可以有多个互斥体
  • 不要过于复杂:您可以使用单个互斥锁来保护对结构中两个元素之一的访问,即,修改mapint的任何操作都可以共享相同的内容单个互斥锁
  • 从其他函数引用结构时-像方法一样使用指针-确保不复制该结构。复制的结构(带有互斥体)将导致不可预测/不安全的结果

从golang mutex docs

  

不应复制包含此包中定义的类型(即sync.Mutux)的值。