You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

78 lines
8.4 KiB
Markdown

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# 结束语 | 再聊Go并发编程的价值和精进之路
你好,我是鸟窝。很高兴和你一起度过了一个多月的时间,到了和你说再见的时候了。
在过去的这些年里我一直在研究Go并发编程时间越久越觉得掌握Go并发原语是一件很有意思的事情。
很多刚开始学习并发原语的同学给我留言说:“**使用Go写并发程序很容易啊为啥要学这么多并发原语呢”**
如果你也有这样的疑问,我的答案就是在这节课的封面图中写的那句话:“**并发原语,初识时简单,深交时复杂,熟识时又觉简单。**”这是我的真实体会。
如果你处于刚开始接触并发原语的阶段,你可能会觉得:“这挺好理解的呀,我一看就会了。”但是随着学习的不断深入,你会看到各种复杂的用法,各种潜在的坑,这些东西打破了初印象,你会陷入到“千头万绪”的境地。只要你不畏困难,持续学习,最后你就可以轻松地使用这些并发原语了。如果说最初的“简单”是“初生牛犊不怕虎”的“简单”,那么“熟识”后的“简单”,就是“拨云见雾”的“简单”。这也是,我在这门课里想要带你达到的状态。
总之,**使用Go写并发程序很容易使用Go写好并发程序很不容易。**
遗憾的是很多人都没有意识并发编程的复杂性甚至还没有意识到并发编程错误带来的严重后果。所以我想跟你分享关于并发编程Bug的两个小故事。
第一个故事是我刚刚看到的澳大利亚交易所ASX的新系统在上线后崩溃的故事。
11月16 日中午ASX发布声明说当天将休市会在次日的正常时间重新开放。官方给出的关闭原因是“局限于单个交易指令中交易多种证券组合交易的软件问题导致了市场数据不准确。”
虽然我并没有看到这个Bug的细节但是从官方提供的关闭原因中我们可以简单地推断出是“单个指令中交易多种证券的问题”大概率是一个并发问题的Bug。虽然经过一天的排查和修复第二天这个交易所就恢复上线了。但是耽误一天的时间损失也是非常大的。
类似的软件Bug尤其是并发问题的Bug即使经过很长时间的测试也不一定能被触发和发现。可是一旦出现就可能是一个一级的Bug。
如果看完这个故事,你还没有意识到并发编程的复杂性和并发问题的危害,我再给你讲一个故事。
1997年7月NASA 的 Mars Pathfinder火星探路者在降落火星表面后不久就因并发软件中的一个缺陷受到了威胁。这是在飞行前的测试中发现的但因为它只发生在某些没有预料到的重载条件下所以被给予了较低的优先级。
但是,飞船开始采集气象数据的时候,它所使用的 vxWorks 操作系统就出现了问题不断地重启。这是经典的优先级反转的并发Bug。
幸好工程师上传了一小段 C 语言程序给飞船,在运行的时候,将优先级继承的互斥标志从 false 改成了 true才成功地解决了这个Bug。
这次人为的忽视,险些酿成惨剧。所以,学好并发编程,是我们的重要责任。
那么该怎么在编写Go程序时避免并发编程的Bug呢在[开篇词](https://time.geekbang.org/column/article/294849)里,我讲到了“两大主线”,现在学完了所有内容之后,你会发现,其实可以抽象成“三部曲”:
1. 全面地掌握Go并发编程的知识不遗漏任何的知识点
2. 熟悉每一个并发原语的功能和实现,在面对并发场景时,能够高效地选出最适合的并发原语;
3. 多看看别人踩的坑,避免自己再掉进相同的坑里。
在前面的课程中,我讲的所有内容,都是为了帮助你轻松地完成这三个目标。在课程的最后,我还想再给你多交代几句。
学完这门课并不代表你已经掌握了Go并发编程的知识。Go并发编程的知识广、内容深现在你再回顾前面的知识可能已经遗忘了一大半了。即使你现在记得很清楚等过一段时间再提到这些知识点你也可能答不上来。
所以,学完这门课并不是一件一劳永逸的事情,你要在空闲的时候多复习下前面的内容。怎么复习呢?你可能也注意到了,每讲完一个并发原语,课程里都有一张知识导图,这些图既可以帮助你梳理知识主线,也可以帮助你高效地复习。
你可以对照着图中的核心要点,去回顾我们学习的重要内容,如果感觉有些地方比较陌生了,就及时回去复习下。另外,你也可以做一些摘录,并且写上你自己的收获和思考。**学习过不等于能输出**,你一定要记住这句话。
另外这门课的核心是讲Go并发原语的知识并没有涉及到Go并发模型和调度的事情。这不是说我认为这部分内容不重要而是很多大牛已经把这些内容写得很清楚、很明白了。如果你对这方面的知识还不太熟悉可以搜索关键字“golang gpm schedule”你会看到很多资料。你读几篇就明白了。如果要推荐的话我建议你重点读一读欧长坤的 [《Go语言原本》的 并发调度](https://golang.design/under-the-hood/zh-cn/part2runtime/ch06sched/),这一篇的逻辑非常顺畅,能看出非常多的经验。
当然,我还想再给你推荐一些补充资料,如果你还有余力,可以再扩展一下知识面。
首先是一本书名字是“Concurrency in Go”。这是第一本全面介绍Go并发编程的图书。书中介绍了并发编程的背景知识、常见的原语和并发模式。我印象最深的就是书里对Channel的介绍比如Channel是粘合goroutine的胶水而select是粘合Channel的胶水。这样形象的说法可以帮助你快速地学到精髓。
除此之外Go官方博客列出的一些技术分享比如[Go Concurrency Patterns](https://www.youtube.com/watch?v=f6kdp27TYZs)、[Advanced Go Concurrency Patterns](https://www.youtube.com/watch?v=QDDwwePbDtw),都是不错的阅读材料,我建议你好好读一读。
好了,关于结课后的学习方法,我就说到这里。在这节课的最后,我特别想再和你分享我自己的两个心得。
**第一,开放的心态,可以拓展你的人生边界。**
我始终认为,一个人衰老的标志,不是指他的容貌经历了太多岁月的刻画,而是他的内心封闭了,不再接收新的知识、新的事物。
在一些技术交流会上我听到一些开发者说Go并发编程很简单有什么可学的遇到这种不是技术讨论的话题我一般只会说“你说得对。”
我当然认同我们应该把核心精力用在眼下有价值的事情上,在自己擅长的领域里深耕,但是我更相信,开放心会让你的人生与众不同。如果你碰见了新技术的发展,即使不需要深入地学习,也要尽量花时间去了解一下,也许这些新的东西,就是你人生的转折点。
我之前就是一直使用Java、Scala后来才开始了解Go但是很显然Go给我的人生带来了不一样的东西。如果不是深入研究Go我就没有机会开设这么一门课了。
**第二,无数人想要你的注意力,但只有你能决定你把它放在哪里。**
我们总说这个时代是信息爆炸的时代,其实,信息爆炸就意味着千万的信息发送者想要占用你的注意力。你一定要保持谨慎,不要毫无感知地把你的时间扔给无价值、无意义的信息。
如果说上一条是让你延伸注意力的触角,那么这一条,就是让你收缩注意力的触角,但这两者并不矛盾,因为侧重点不同。“延伸”还是“收缩”,取决于你自己想要拥有的人生的样子,只有你能决定。我能做的,就是提醒你,要开放,也要谨慎。
虽然很舍不得但还是要跟你说再见了。在课程的最后我给你准备一份结课问卷希望你花1分钟时间点击下面的图片填写一下。如果你的建议被采纳我将会给你赠送一个护腕垫或者价值99元的课程阅码。期待你的畅所欲言。
[![](https://static001.geekbang.org/resource/image/2e/9b/2eab2acf71e5183e59ea9a10e08eee9b.jpg)](https://jinshuju.net/f/UQheYe)