golang mutex有时会起作用吗?

时间:2017-03-21 03:55:48

标签: go maps mutex

我有以下goroutine,SOMETIMES生成可怕的“致命错误:并发映射读取和映射写入”。 Traceback在s:= db.FileInfo ... map reference。

上显示它
func HMAC(source string, i int) {
    var value [4]byte
    var mutex sync.Mutex
    defer WG.Done()
    hash, err := HashString(source);
    if err != nil {
            log.Critical("HashString error: ",err)
    }
    log.Trace("Slice:",i,"Authentication hash =",hash)
    rand.Seed(time.Now().UnixNano())
    mutex.Lock()    // Protect Map activity
    defer mutex.Unlock()
    s := db.FileInfo.Slices[SliceName]
    s.Block[i].HMAC = hash
    for j:=0; j<32; j++ {
            off := rand.Intn(DataLen-5)  // 4 should do, but be safe
            s.Block[i].Random[j].Offset = off
            for k:=0; k<4; k++ {
                    value[k] = source[off+k]
            }
            s.Block[i].Random[j].Value = value
    }
    db.FileInfo.Slices[SliceName] = s
}

HashString(source)函数是计算密集型的,因此适合作为goroutine。互斥锁调用之后的代码在计算上都是相对微不足道的,占用HashString(源)调用所花费的时间不到1%。 go vet在例程及其来电者身上是干净的。

此函数调用(32)次,如下所示:

    util.WG.Add(32)
    for i:=0; i<32; i++ {
            off := i*util.BlockLen
            go util.HMAC(string(tblock[off:off+util.BlockLen-1]),i)
    }
    util.WG.Wait()

我从程序的每六个左右调用中得到一次错误,非常不一致。

有人发现我做错了吗?这个问题的某些性质令我感到困惑。哦,FWIW,它运行在12线程I7上。另外:go go go7.7.5 linux / amd64。

2 个答案:

答案 0 :(得分:6)

每次执行该函数都会创建一个新的互斥锁,因此它实际上并没有保护任何东西。您需要让函数始终在其他地方使用相同的互斥锁(例如,作为全局变量)。

答案 1 :(得分:0)

使互斥变量在您的函数中不是本地的。这是固定代码:

var mutex sync.Mutex

func HMAC(source string, i int) {
    var value [4]byte
    // var mutex sync.Mutex
    defer WG.Done()
    ...