2017-03-21 7 views
1

私は次のようなゴルーチンを持っています。時には恐ろしい "致命的なエラー:同時マップ読み取りとマップ書き込み"が発生します。トレースバックは、s:= db.FileInfo ...マップ参照でそのことを示します。golang mutexが動作することがありますか?

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(ソース)関数は計算集約的なので、ゴルーチンとしては適切です。ミューテックス呼び出しの後のコードは、すべて計算的に比較的簡単で、HashString(ソース)呼び出しにかかる時間の1%未満を占めます。獣医はルーチンとその呼び出し元できれいです。

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() 

私は非常にinconsistantly、プログラムのすべての半ダースかそこらの呼び出しの外に一回程度のエラーが表示されます。次のように

この関数は、(32)回と呼ばれています。

誰かが私が間違っていることを察知していますか?この問題の時折、私は困惑しています。ああ、FWIW、12スレッドI7で動作している。また:行くバージョンgo1.7.5 linux/amd64。

答えて

5

この関数を実行するたびに新しいミューテックスが作成されるため、実際に何も保護していません。この関数には常に同じmutexを使用する必要があります(グローバル変数など)。

+0

ありがとうございますAndy。それは私が夜のために置いた後約20秒に起こった... – Cassey

0

mutex変数は、関数内でローカルではありません。これは固定コードです。

var mutex sync.Mutex 

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