并发map或者类似的结构

请问我目前有这么一个需求: map[string]item{ key1:value1, key2:value2, key3:value3 } 这么一个数据结构,目前存在多个线程更新数据,多个线程读取数据,但是针对同一个key的数据,只会同时存在一个线程更新,多个线程读取的情况。 请问目前有方便高效的解决方案吗? 类似 java ConcurrentHashMap 的go实现有么?
已邀请:

lrita

赞同来自: Xanthus codinghxl

* map中key的数量不经常变更时,不add/delete key,只变更value,`sync.Map`效率优于`concurrent-map`。
* 如果存在大量key数量变更时,经常add/delete key,`concurrent-map`优于`sync.Map`。

gogoing

赞同来自: jitongxi

Go 1.9 sync.Map

Xanthus - 红红火火恍恍惚惚

赞同来自: mnhkahn

1.9的sync.Map也是有全局锁的,如果想作为内存数据库用,还是自己实现吧。
[concurrent-map](https://github.com/orcaman/concurrent-map)的实现与Java中concurrentHashMap类似,用多把锁,锁对应的桶。这种方式主要是注意key的均匀分布。
concurrent-map是用fnv32处理string类型的key。不过实际上的key经常是id,可以直接简单地取余来确定放哪个桶
```golang
type CMap struct {
slotCnt int64
buckets []map[int64]interface{}
locks []*sync.RWMutex
}

func (m *CMap) Init(cnt uint8) {
if cnt == 0 {
cnt = 1
}
m.slotCnt = int64(cnt)
// 初始化m.buckets
// 初始化m.locks
}

func (m *CMap) Set(key int64, v interface{}) {
if m.slotCnt == 0 {
m.Init(1)
}
slot := key % m.slotCnt
l := m.locks[slot]
l.Lock()
m.buckets[slot][key] = v
l.Unlock()
}
```

SaltySailor

赞同来自: codinghxl

我大概想到两个点:
1.关于map这类数据结构如果用锁的话考虑给数据分片,分成若干个片然后给每个片配一把锁,细化一下锁的颗粒度,有效减少冲突。
2.针对你这种“只会同时存在一个线程更新,多个线程读取的情况”也就是读多写少的情景,考虑用copy-on-write优化,具体含义可以google一下。

pathbox - https://pathbox.github.io/

据说 Go 1.9 sync.Map 性能比自己用sync.Metux map 好
golang 没有完善的 concurrent map 实现,开源版是一个固定的并发度(无选项)

建议参考 java,修改一个自己的版本

要回复问题请先登录注册