使用互斥锁,但仍可进行并发映射写入

时间:2018-12-09 09:15:17

标签: go

我有一张地图,想要手动进一步分片,简化后的代码是

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,但是我确实锁定了互斥锁,不确定我的代码有什么问题

2 个答案:

答案 0 :(得分:5)

  

Package sync

import "sync"
     

type Mutex

     

互斥锁是互斥锁。互斥锁的零值为   解锁的互斥锁。

     

互斥量不得在首次使用后复制。


您的代码无法编译!

游乐场: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() {}

  

Command vet

     

兽医检查Go源代码并报告可疑结构

     

Copying locks

     

标志:-copylocks

     

错误地按值传递的锁。

答案 1 :(得分:0)

我认为答案与复制互斥锁值有关。 字典should

type dict struct {
    shards []*shard
}

所有shard都是通过指针访问的,因此不会有任何问题。