我有一张地图,想要手动进一步分片,简化后的代码是
const (
dictShardNum = 16
dictShardSize = 1 << 28
)
type shard struct {
mu sync.Mutex
m map[int64]uint32
}
type dict struct {
shards []shard
}
func newDict() *dict {
shards := make([]shard, 0, dictShardNum)
for i := 0; i < dictShardNum; i++ {
shards = append(shards, shard{ m: make(map[int64]uint32) })
}
return &dict{ shards }
}
func (d *dict) insert(n int64) uint32 {
shardNum := int(n % dictShardNum)
shard := d.shards[shardNum]
shard.mu.Lock()
defer shard.mu.Unlock()
tempID, ok := shard.m[n]
if !ok {
tempID = uint32(len(shard.m) + shardNum*dictShardSize)
shard.m[n] = tempID // fatal error: concurrent map writes
}
return tempID
}
运行时,我在该行得到了fatal error: concurrent map writes
,但是我确实锁定了互斥锁,不确定我的代码有什么问题
答案 0 :(得分:5)
import "sync"
互斥锁是互斥锁。互斥锁的零值为 解锁的互斥锁。
互斥量不得在首次使用后复制。
您的代码无法编译!
游乐场:https://play.golang.org/p/6AwS0vOZfeP
25:18: undefined: n
30:24: undefined: n
33:11: undefined: n
如果我将v int64
更改为n int64
:
互斥量不得在首次使用后复制。
$ go vet mutex.go
./mutex.go:26:11: assignment copies lock value to shard: command-line-arguments.shard contains sync.Mutex
$
游乐场:https://play.golang.org/p/jExE-m11ny5
package main
import (
"sync"
)
const (
dictShardNum = 16
dictShardSize = 1 << 28
)
type shard struct {
mu sync.Mutex
m map[int64]uint32
}
type dict struct {
shards []shard
}
/// a newDict function
func (d *dict) insert(n int64) uint32 {
shardNum := int(n % dictShardNum)
shard := d.shards[shardNum]
shard.mu.Lock()
defer shard.mu.Unlock()
tempID, ok := shard.m[n]
if !ok {
tempID = uint32(len(shard.m) + shardNum*dictShardSize)
shard.m[n] = tempID // fatal error: concurrent map writes
}
return tempID
}
func main() {}
兽医检查Go源代码并报告可疑结构
标志:-copylocks
错误地按值传递的锁。
答案 1 :(得分:0)
我认为答案与复制互斥锁值有关。
字典should
是
type dict struct {
shards []*shard
}
所有shard
都是通过指针访问的,因此不会有任何问题。