深入理解golang:sync.map (3)

根据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源码

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wsffdg.html