在 Go 中组合存储在通道上的多个映射(相同键的值求和。)
来源:stackoverflow
时间:2024-04-22 12:30:36 170浏览 收藏
大家好,我们又见面了啊~本文《在 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"))
输出(在 Go Playground 上尝试):
map[a:1 aa:2 ab:1 cd:3 de:1 ef:1 x:1]
另请注意,理论上这看起来“不错”,但实际上您可能仍然无法实现任何性能提升,因为 goroutine 所做的工作太“少”,并且启动它们并合并结果需要付出努力,这可能会超过收益.
今天带大家了解了的相关知识,希望对你有所帮助;关于Golang的技术知识我们会一点点深入介绍,欢迎大家关注golang学习网公众号,一起学习编程~
-
502 收藏
-
502 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
139 收藏
-
204 收藏
-
325 收藏
-
477 收藏
-
486 收藏
-
439 收藏
-
357 收藏
-
352 收藏
-
101 收藏
-
440 收藏
-
212 收藏
-
143 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 542次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 508次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 497次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 484次学习