golang mutex 有时有效?
golang mutex sometimes works?
我有以下 goroutine,有时会生成可怕的 "fatal error: concurrent map read and map write"。 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(source) 调用所用时间的 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 version go1.7.5 linux/amd64.
函数的每次执行都会创建一个新的互斥体,因此它实际上并没有保护任何东西。您需要通过在别处创建它(例如,作为全局变量)来让该函数始终使用相同的互斥量。
使 mutex 变量不在您的函数中。这是固定码:
var mutex sync.Mutex
func HMAC(source string, i int) {
var value [4]byte
// var mutex sync.Mutex
defer WG.Done()
...
我有以下 goroutine,有时会生成可怕的 "fatal error: concurrent map read and map write"。 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(source) 调用所用时间的 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 version go1.7.5 linux/amd64.
函数的每次执行都会创建一个新的互斥体,因此它实际上并没有保护任何东西。您需要通过在别处创建它(例如,作为全局变量)来让该函数始终使用相同的互斥量。
使 mutex 变量不在您的函数中。这是固定码:
var mutex sync.Mutex
func HMAC(source string, i int) {
var value [4]byte
// var mutex sync.Mutex
defer WG.Done()
...