当前位置: > > > > 在 Go 中组合存储在通道上的多个映射(相同键的值求和。)
来源:stackoverflow
2024-04-22 12:30:36
0浏览
收藏
大家好,我们又见面了啊~本文《在 Go 中组合存储在通道上的多个映射(相同键的值求和。)》的内容中将会涉及到等等。如果你正在学习Golang相关知识,欢迎关注我,以后会给大家带来更多Golang相关文章,希望我们能一起进步!下面就开始本文的正式内容~
问题内容
我的目标是创建一个程序,以并行方式计算文本文件中每个唯一单词的出现次数,所有出现的次数都必须在单个地图中呈现。
我在这里所做的是将文本文件划分为字符串,然后划分为数组。然后将该数组分为两个长度相等的切片,并同时馈送到映射器函数。
func wordcount(text string) (map[string]int) { wg := new(sync.waitgroup) s := strings.fields(newtext) freq := make(map[string]int,len(s)) channel := make(chan map[string]int,2) wg.add(1) go mappers(s[0:(len(s)/2)], freq, channel,wg) wg.add(1) go mappers(s[(len(s)/2):], freq, channel,wg) wg.wait() actualmap := <-channel return actualmap
func mappers(slice []string, occurrences map[string]int, ch chan map[string]int, wg *sync.waitgroup) { var l = sync.mutex{} for _, word := range slice { l.lock() occurrences[word]++ l.unlock() } ch <- occurrences wg.done() }
最重要的是,我收到了一个以
开头的巨大多行错误
致命错误:并发映射写入
当我运行代码时。我以为我是通过互斥来守护的
l.Lock() occurrences[word]++ l.Unlock()
我在这里做错了什么?而且。如何将所有地图合并到一个频道中?对于组合,我的意思是相同键的值在新映射中求和。
解决方案
主要问题是在每个 goroutine 中使用单独的锁。这对于序列化对地图的访问没有任何帮助。每个 goroutine 必须使用相同的锁。
由于您在每个 goroutine 中使用相同的映射,因此您不必合并它们,也不需要通道来传递结果。
即使您在每个 goroutine 中使用相同的互斥锁,由于您使用单个映射,这可能对性能没有帮助,goroutine 将不得不相互竞争映射的锁。
您应该在每个 goroutine 中创建一个单独的映射,使用它在本地进行计数,然后将结果映射传递到通道上。这可能会给您带来性能提升。
但是你不需要锁,因为每个 goroutine 都有自己的映射,它可以在没有互斥体的情况下读/写。
但是您必须在通道上传递结果,然后合并它。
由于 goroutine 在通道上传递结果,因此等待组变得不必要。
func wordcount(text string) map[string]int { s := strings.fields(text) channel := make(chan map[string]int, 2) go mappers(s[0:(len(s)/2)], channel) go mappers(s[(len(s)/2):], channel) total := map[string]int{} for i := 0; i < 2; i++ { m := <-channel for k, v := range m { total[k] += v } } return total } func mappers(slice []string, ch chan map[string]int) { occurrences := map[string]int{} for _, word := range slice { occurrences[word]++ } ch <- occurrences }
测试示例:
fmt.println(wordcount("aa ab cd cd de ef a x cd aa"))
输出(在 上尝试):
map[a:1 aa:2 ab:1 cd:3 de:1 ef:1 x:1]
另请注意,理论上这看起来“不错”,但实际上您可能仍然无法实现任何性能提升,因为 goroutine 所做的工作太“少”,并且启动它们并合并结果需要付出努力,这可能会超过收益.
今天带大家了解了的相关知识,希望对你有所帮助;关于Golang的技术知识我们会一点点深入介绍,欢迎大家关注公众号,一起学习编程~