根据key删除一个值:
// src/sync/map.go // Delete deletes the value for a key. func (m *Map) Delete(key interface{}) { // 从 m.read 中开始查找 read, _ := m.read.Load().(readOnly) e, ok := read.m[key] if !ok && read.amended { // m.read中没有找到,并且可能存在于m.dirty中,加锁查找 m.mu.Lock() // 加锁 read, _ = m.read.Load().(readOnly) // 再在m.read中查找一次 e, ok = read.m[key] if !ok && read.amended { //m.read中又没找到,amended标志位true,说明在m.dirty中 delete(m.dirty, key) // 删除 } m.mu.Unlock() } if ok { // 在 m.ready 中就直接删除 e.delete() } }还有更好的方法没?java里面有一个分段锁,保证在操作不同 map 段的时候, 可以并发执行, 操作同段 map 的时候,进行锁的竞争和等待。从而达到线程安全, 且效率大于 synchronized。而不是直接加一把大锁,锁住整个map。
那go里面有木有?有人已经想到了
concurrent-map项目地址:concurrent-map
中文wiki:地址
正如 和 这里 所描述的, Go语言原生的map类型并不支持并发读写。concurrent-map提供了一种高性能的解决方案:通过对内部map进行分片,降低锁粒度,从而达到最少的锁等待时间(锁冲突)。
在Go 1.9之前,go语言标准库中并没有实现并发map。在Go 1.9中,引入了sync.Map。新的sync.Map与此concurrent-map有几个关键区别。标准库中的sync.Map是专为append-only场景设计的。因此,如果您想将Map用于一个类似内存数据库,那么使用我们的版本可能会受益。你可以在golang repo上读到更多,这里 and 这里
译注: sync.Map在读多写少性能比较好,否则并发性能很差
有兴趣的可以自己研究下。
参考:Go 1.9 sync.Map揭秘
go sync.Map使用和介绍
golang sync.map源码