Mutex - 全局或本地和惯用用法?

Mutex - global or local and idiomatic usage?

阅读 golang.org 和 Whosebug 上的互斥示例后,我仍然不确定匿名函数的声明和惯用用法。所以我总结了几个例子。

示例 A、B 和 C 是否几乎相同,或者是否存在我没​​有注意到的重大差异? 我更喜欢全局示例“B”。我想如果我小心翼翼,这可能是最简单的解决方案。

或者是否有更好的方法来使用互斥量?

This example on go playground

package main

import (
    "fmt"
    "sync"
)

type MuContainer struct {
    sync.RWMutex
    data int
}

var mucglobal = &MuContainer{}

func main() {

    // A: Global declaration - working: adds 45
    for i := 0; i < 10; i++ {
        go func(j int, mucf *MuContainer) {
            mucf.Lock()
            mucf.data += j
            mucf.Unlock()
        }(i, mucglobal)
    }

    // B: Global only - working: adds 45
    for i := 0; i < 10; i++ {
        go func(j int) {
            mucglobal.Lock()
            mucglobal.data += j
            mucglobal.Unlock()
        }(i)
    }

    // C: Local declaration - working: adds 45
    muclocal := &MuContainer{}
    for i := 0; i < 10; i++ {
        go func(j int, mucf *MuContainer) {
            mucf.Lock()
            mucf.data += j
            mucf.Unlock()
        }(i, muclocal)
    }

    // // D: Pointer to struct - not working: adds 0
    // // I guess because it points directly to the struct.
    // for i := 0; i < 10; i++ {
    //  go func(j int, mucf *MuContainer) {
    //      mucf.Lock()
    //      mucf.data += j
    //      mucf.Unlock()
    //  }(i, &MuContainer{})
    // }

    for {
        mucglobal.RLock()
        muclocal.RLock()
        fmt.Printf("global: %d / local: %d\n", mucglobal.data, muclocal.data)
        if mucglobal.data == 90 && muclocal.data == 45 {
            muclocal.RUnlock()
            mucglobal.RUnlock()
            break
        }
        muclocal.RUnlock()
        mucglobal.RUnlock()
    }
}

D 不起作用,因为您正在为每次迭代创建一个新结构。最后,您将拥有 MuContainer.

的 10 个独立实例

前两个选项在语义上是相同的。这两个的底线是每个 goroutine 共享对象的相同实例,它恰好是一个全局变量。

第二个类似,唯一的区别是锁定和更新的对象恰好是本地变量。同样,goroutines 在对象的同一个实例上工作。

所以这些其实并没有什么区别,三者各有用途。