Go 天生是为并发而生的东西。简单来说,我觉得并发可以看作一种程序的构造方式,如下图所示。
并行&并发
想了解并行和并发的区别,推荐看一下Rob Pike的分享(点击阅读原文即可跳转)。在这个视频里,他用形象的Gopher动图,讲解了Go并发的过程。
总结他的观点如下:
因为今天的重点不是讲理论,而是站在可视化的角度来展示并发的过程。所以,结合这两个可视化图形可以直观的了解并发和并行的区别,毕竟一图胜千言。(请复制链接在浏览器中打开)
并发:http://talks.bingohuang.com/2017/go-concurrency-visualize/pingpong36.html并行:http://talks.bingohuang.com/2017/go-concurrency-visualize/parallelism.html总的来说,并行就是同时执行(通常是相关的)计算任务的编程技术,两个或者多个事件在同一时刻发生;而并发是将相互独立的执行过程综合到一起的编程技术,两个或多个事件在同一时间间隔内发生。
为什么要关注并发?
当今是多核的时代,并发的世界。摩尔定律逐渐失效,需要更多关注并发的编程思想。
但并发编程并不容易,而 Go 对并发有很好的支持。
Go 语言中的并发
Goroutine – 并发执行
类似于 UNIX 中的 &很像线程,但更轻量一个 goroutine 就是一个独立运行的函数当一个 goroutine 阻塞时,所在的线程会阻塞,但其它 goroutine 不受影响通过关键字 go 来创建 goroutine,如下说是
Channel
类似于 UNIX 中的管道它允许在 Goroutine 之间传递消息如下有一个简单的例子,这是常见的计时器,后续还可以做成可视化的图形。
Select
类似于语言中常见的 switch但它的判断条件是基于通信,而不是基于值的等量匹配Go让并发编程变得简单起来
但问题来了:
我们怎样去讲解 Go 的并发?我们怎样思考 Go 的并发过程?最终,我们怎样更好的实践 Go 并发编程?这里祭出一个法宝——GoTrace,它是一个能将 Go 并发过程可视化的开源工具,出自 divan 大神。主要包含两个程序:
gotrace(go):分析 go tool trace 的执行结果gothree(js): 基于 ThreeJs 和 WebGL 生成 3D 图像感谢 divan 大神 提供了这款工具和不少 Go 并发模式的素材。
耳听为虚,眼见为实
1.Hello,World!
无论写什么语言,都会从 hello world开始,代码非常简单 – 单 channel,单 goroutine,一次写,一次读。
效果如下图(复制链接 http://talks.bingohuang.com/2017/go-concurrency-visualize/helloworld.html 在浏览器中打开也可直接访问):
这里蓝色的线表示 goroutine 随着时间运行。细的蓝线连接了 ‘main’ 和 ‘#20’,标志着 goroutine 的启动和停止,揭示了它们的父子关系。最后,红色箭头给我们展示了‘发送/接受’的动作。实际上它是两个独立的动作,我试着用动画展示成一个单独的事务:从 A 发送到 B。 Goroutine 名称中的的 “#20”,是实际的 goroutine 内部 ID,通过某种手段从运行时获取。
2.计时器
记得在前面讲Channel举的一个计时器的例子,也非常典型 – 创建一个 channel,启动一个 goroutine,在给定的时间间隔之后向这个 channle 写入数据,之后将这个 channel 返回给函数的调用着。这个调用者会阻塞固定的时间后去读取该 channel。让我们来运行 24 个这样的计时器并试着做可视化。
看一下效果(复制链接http://talks.bingohuang.com/2017/go-concurrency-visualize/timer.html):
非常的形象,是不是?
3.兵乓球
两个玩家
看一下效果(复制链接 http://talks.bingohuang.com/2017/go-concurrency-visualize/pingpong2.html 到浏览器中打开)
建议在PC端浏览器上打开上面的链接,可以和 WebGL 动画交互,玩玩看。你可以放慢、加快,从不同的角度观察它。
三个玩家
上面是常见的2个乒乓球运动员对打的过程,如果是三个运动员会是什么样呢?现在,让我们来运行 3 个运动员的试试看。代码中只要做少量的修改,添加一个 player 即可:
效果如下:(复制链接 http://talks.bingohuang.com/2017/go-concurrency-visualize/pingpong3.html 到浏览器中打开)
36个玩家
让我们看一个更复杂的例子,跑36个运动员看看。
效果(复制链接http://talks.bingohuang.com/2017/go-concurrency-visualize/pingpong36.html 在浏览器中打开)
在这里我们看到每个运动员都是轮流依次进行,你可能会想为什么是这样?为什么接球的 goroutine 会依照这么严格的顺序?
答案是因为 Go 运行时给接受者(准备从特定的 channel 接收消息的 goroutines)保持一个先进先出(FIFO)的队列,同时在我们的例子中,每一个运动员正好在他将球打到桌子上的时候就做好准备。
4.素数筛
上面几个例子比较简单,让我们来看一个更复杂的并发算法:素数筛算法,又叫埃拉托斯特尼算法,是一种古老的算法,用于找到小于或等于给定整数n的素数。算法核心思想:先用最小的素数2去筛,把2的倍数剔除掉;下一个未筛除的数就是素数(这里是3)。再用这个素数3去筛,筛除掉3的倍数… 这样不断重复下去,直到筛完为止。
这个算法的并发变化是用 goroutines 来过滤数字 —— 一个 goroutine 发现一个素数,而 channels 用来把数字从 generator 传递到 filter。当一个素数被找到了,就会通过 channel 传递给 main,再输出。
当然,这个算法并不会非常高效,特别是在你想找大量的素数,并且寻找最低的大 O 复杂度时,但这个算法确非常的优雅。
大家可以看一下可视化的样子(http://talks.bingohuang.com/2017/go-concurrency-visualize/primesieve.html)
可以在交互模式中体验一下该动画。它的图形化方式确实能更好的帮助我们理解算法。该 generate 函数 goroutine 从 2 开始发出每一个整数。而每一个新的 filter 函数 goroutine 会过滤特定素数的倍数 – 2,3,5,7……每一个 filter 的第一个数就是素数,将它发送给 main 函数,并输出。如果你旋转图像自顶向下看的话,你会发现,所有从 goroutine 发送给 main 的数字就是素数。
非常漂亮的算法,特别是在 3D 图像下。
5.其他-Goroutines 泄漏
虽然说Goroutine是一个很轻量线程,不应该浪费它的。假设有N多个Goroutine泄漏了会怎么样?
效果见http://talks.bingohuang.com/2017/go-concurrency-visualize/leak.html
看起来很漂亮,但它是一个定时炸弹,所以平时编码的时候一定要注意Goroutine泄漏的问题。
Gotrace的用法简介
最后说一下GoTrace的用法,它本身也是开源的。
下载方式:go get -v -u github.com/divan/gotrace
默认分支(master)是基于 Go 1.6 开发,我建议切换到到 Go18 分支,支持 Go 1.8。
具体用法如下:
直接运行 go 代码的效果并不好,推荐生成 trace,需在执行的代码上前后加上:
结合 docker ,可以用以下脚本:
它会自动打开这个浏览器,可以调整视角,可以缩放、旋转、加粗,改变图像。
使用场景
最后我想说一下使用场景。首先,我看到的时候觉得非常酷,这会引发大家对学习Go的兴趣,同时还可以通过它来学习 Go 的并发模式,探索 Go 的并发过程,希望对大家进一步学习 Go 语言有所帮助。
- 蜜度索骥:以跨模态检索技术助力“企宣”向上生长
- 央国企采购管理升级,合合信息旗下启信慧眼以科技破局难点
- Apache Struts重大漏洞被黑客利用,远程代码执行风险加剧
- Crunchbase:2024年AI网络安全行业风险投资超过26亿美元
- 调查报告:AI与云重塑IT格局,77%的IT领导者视网络安全为首要挑战
- 长江存储发布声明:从无“借壳上市”意愿
- 泛微·数智大脑Xiaoe.AI正式发布,千人现场体验数智化运营场景
- IDC:2024年第三季度北美IT分销商收入增长至202亿美元
- AI成为双刃剑!凯捷调查:97%组织遭遇过GenAI漏洞攻击
- openEuler开源五年树立新里程碑,累计装机量突破1000万
- 创想 华彩新程!2024柯尼卡美能达媒体沟通会焕新增长之道
免责声明:本网站内容主要来自原创、合作伙伴供稿和第三方自媒体作者投稿,凡在本网站出现的信息,均仅供参考。本网站将尽力确保所提供信息的准确性及可靠性,但不保证有关资料的准确性及可靠性,读者在使用前请进一步核实,并对任何自主决定的行为负责。本网站对有关资料所引致的错误、不确或遗漏,概不负任何法律责任。任何单位或个人认为本网站中的网页或链接内容可能涉嫌侵犯其知识产权或存在不实内容时,应及时向本网站提出书面权利通知或不实情况说明,并提供身份证明、权属证明及详细侵权或不实情况证明。本网站在收到上述法律文件后,将会依法尽快联系相关文章源头核实,沟通删除相关内容或断开相关链接。