Golang Go语言中多协程操作同一个 map 的方案哪个好

发布于 1周前 作者 sinazl 来自 Go语言

Golang Go语言中多协程操作同一个 map 的方案哪个好

多个协程读写 map,读多写少。(就是定时加载配置) 现在的方式是定义一个指针指向 map,tM = *map[int]*sT。

然后读的时候,原子操作 load 这个指针: rM := (*map[int]*sT)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&tM))))

写的时候,先创建一个 map ( tmp ),填好信息后,然后再原子操作: atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&tM)), unsafe.Pointer(&tmp))。

除此之外,知道还有读写锁,sync.Map ,atomic.Value,不知道哪个性能最好?(即读的时候要快,因为有好多数据要通过这个 map 匹配)

另外,如果是读写差不多的情况下,是不是 sync.Map 最合适?


更多关于Golang Go语言中多协程操作同一个 map 的方案哪个好的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html

19 回复

sync.Map 适合你的描述

更多关于Golang Go语言中多协程操作同一个 map 的方案哪个好的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


不知道 sync.Map 是怎么实现的,但肯定有一些同步的判断吧,所以每次读都会比正常的 map 要慢一点,数据一多,就会慢的多了。这样理解对不?

这种情况的话,是 atomic.Value 最好,官方的示例程序就是你这里的场景。
http://blog.betacat.io/post/golang-atomic-value-exploration/

大多数时候加个锁并没有想象中那么慢,特别是本来就是读多的场景

之前看到过,想的是,每次读都要 load 一下,肯定不能比我一个原子操作还快吧。所以没用,当然这只是想的,没经过验证,不会基测。。。

现在 3 分钟内,150 万次读这个 map,如果每次读都加一个读锁,感觉开销有点大啊。也并没有要求那么高,数据来的比较集中,但有 kafka 做缓冲,所以可以慢点也没事,只是我想找一个性能最好的方式。

每个 goroutine 每秒检查一次配置有没有更新就行了,没有必要跑一次读一次。

sync.Map 最省心,缺点是没法用 len,也没法获取 size,只能在 Range 里面自己计数。

用内建 map 读多写少的情况最好还是 sync.RWMutex

sync.map 比你快,大牛单手写的代码,用的是 cache,大部分情况不加锁的,c++,Java 新官方都开始学习这个

标准问题尽量用 STL,如果你的平均性能超过 STL,直接入选 golang 技术委员会,

写代码测试一下不就知道了。

标准库未必就是性能最佳吧,就说 json,你用的是标准库中的?另外,sync.map 肯定不是为了多读少写场景设计的,如果说是 atomic.Value 到是,这个也是无锁的,看了他的实现,里面用了原子操作,还有判断逻辑,与内置的 map 比肯定差。

实话,真不会测试。研究研究也应该能会,想着这个问题应该都有遇到过,如果别人梳理过,系统的测试过,更好。

testing.B 了解以下

用读写锁应该可以把

可以是都可以的,我想要性能最好的,读写锁应该是性能最差的。现在懒得去基测,等有遇到问题再研究。

在Golang中,多个协程(goroutine)操作同一个map时,由于map不是并发安全的,直接操作会引发数据竞争和运行时崩溃。以下是几种常见的解决方案,各有优缺点:

  1. 使用sync.Mutex或sync.RWMutex: 通过互斥锁(Mutex)或读写锁(RWMutex)来保护对map的访问。这种方法简单直接,但会引入锁竞争,影响性能。适用于读多写少的场景时,可以考虑使用RWMutex来提高并发性能。

  2. 使用sync.Map: Go 1.9引入了sync.Map,专为并发场景设计。它内部使用了更复杂的机制来减少锁竞争,适合高并发读写操作。但sync.Map的API与原生map有所不同,且不支持直接迭代所有键值对(需要通过Range方法遍历)。

  3. 使用channel进行通信: 通过channel将数据的读写操作集中到一个或几个goroutine中,由这些goroutine维护一个私有的map。其他goroutine通过channel与这些goroutine通信,从而间接访问map。这种方法可以避免锁竞争,但需要设计好channel的通信机制。

  4. 使用分片(Sharding): 将map拆分成多个小map,每个小map由一个goroutine维护。通过哈希函数将数据分配到不同的小map中,从而减少锁竞争。这种方法适用于数据量非常大且分布均匀的场景。

综上所述,选择哪种方案取决于具体的应用场景和需求。在性能要求较高的场景下,建议进行基准测试以选择最优方案。

回到顶部