# 13. 并发与异步

内核恐慌 · 2015-03-21

<https://lib.pan.icu/d0feea32-1f0b-44d8-8d33-0c45f16b11ce>

本期节目深入探讨了并发（concurrency）与并行（parallelism）的区别，并发是处理多件事的能力，并行是同时执行多件事的能力。吴涛和Rio梳理了四种主流并发模型：传统的线程与锁、函数式编程（消除可变状态）、CSP（通信顺序进程，如Go语言的channel）和Actor模型（如Erlang的邮箱机制）。他们还分析了异步IO与协程，指出异步IO虽能避免锁问题但易陷入回调地狱，而协程则能保留线性逻辑流。节目最后推荐了《Seven Concurrency Models in Seven Weeks》等资源，并鼓励听众捐款支持节目。

## Questions this episode answers

### 并发（Concurrency）和并行（Parallelism）有什么区别？

吴涛和Rio解释，并发指同时应对多件事的能力（如一个人做饭时要洗锅、切菜），并行则指同时动手做多件事（如两个人分工）。他们引用Rob Pike的话：并发是“dealing with a lot of things”，并行是“doing a lot of things at once”。做饭例子里，单人是并发，多人是并行。

[46:36](https://lib.pan.icu/d0feea32-1f0b-44d8-8d33-0c45f16b11ce?t=2796000)

### CSP模型和Actor模型在并发编程中有什么不同？

Rio介绍，CSP（Communicating Sequential Processes）通过channel传递消息，发送方必须等接收方就绪（同步）；Actor模型则通过邮箱异步通信，消息先存进邮箱，接收方稍后处理。Go的channel可带缓冲，兼具Actor特性。两者都封装了锁，但抽象角度不同。

[1:21:03](https://lib.pan.icu/d0feea32-1f0b-44d8-8d33-0c45f16b11ce?t=4863000)

### 什么是异步IO？回调和协程分别如何实现异步编程？

吴涛和Rio指出，异步IO让程序在等待IO时不阻塞，转去执行其他任务。基于回调的异步易陷入“回调地狱”，代码被拆成碎片。协程则保存执行状态，可在阻塞点让出控制权，之后恢复，从而保持代码的线性逻辑，如Python的generator和Go的goroutine。

[1:33:18](https://lib.pan.icu/d0feea32-1f0b-44d8-8d33-0c45f16b11ce?t=5598000)

## Key moments

- **[0:00] 开场**
  - [0:37] 0118 999 881 999 119 7253 被吴涛采纳为节目热线号码，源自《IT Crowd》
  - [1:06] 捐款金额必须为可被 8 整除的正整数，吴涛在节目中宣布
  - [1:47] 第 13 期在十六进制中记为 0x0d，吴涛在开场中换算
  - [2:31] 加拿大的原意是 ‘大农村’（Big Village），Rio 在节目中指出
- **[2:48] 上期回顾**
  - [3:40] Penny 来自 Omaha, Nebraska，来自《生活大爆炸》剧情
  - [4:46] 幕僚那期节目为内核恐慌带来众多女粉丝，Rio 发现后挨个点进微博查看
  - [5:41] “幕僚这一期真的是前无古人后无来者的高度了”，吴涛评价
  - [6:31] 微软员工发来 2200 多字的反馈长信，吴涛和 Rio 在节目中提及
  - [7:47] 吴涛和 Rio 决定，因微软热心听众，以后黑微软会下嘴轻一点
  - [8:27] 现代编程工具比 2005 年好用很多，吴涛举例 Web Console 和 REPL
- **[8:53] 编程工具**
  - [10:37] REPL 代表 Read-Evaluate-Print Loop（读入、求值、打印、循环），Rio 解释
  - [12:15] Swift Playground 提供 Live Programming 能力，被吴涛视为更先进的 REPL
  - [13:29] Smalltalk 的整个环境可被 inspection，Rio 认为其设计惊为天人但未流行
  - [14:16] Worse is better 理念下 Linux 不优雅但流行，Rio 指出
  - [14:53] “流行的语言往往是糟糕的语言”，吴涛感慨
  - [15:59] 电影《剑与行动》中的拖拽方块编程方式，被吴涛设想为革命性编程工具
- **[20:42] 苹果发布**
  - [21:07] 新 MacBook 取消 Air 产品线，只保留 MacBook 和 MacBook Pro，Rio 分析
  - [21:40] 新 MacBook 的 ESC 键保留原位且变大，Rio 称是 Vim 党福音
  - [22:17] 11 寸 MacBook Air 的 ESC 键只有 1/3 高，Rio 吐槽其太小
  - [23:36] 新 MacBook 内存固定 8GB 无法扩展，Rio 认为对开发者不够
  - [24:46] 联想 Convert Tablet 的 Core M 处理器性能与 14 款 MacBook Air 相当
  - [26:09] iOS 开发直接连真机调试只比模拟器慢最多 20 秒，吴涛分享经验
- **[43:53] 并发并行**
  - [44:04] 本期主题为并发与异步，吴涛称将浅入浅出讲解
  - [44:21] “每增加一个公式读者减半”，吴涛引用霍金的话类比术语对听众的影响
  - [45:23] 并发（Concurrency）是逻辑概念，并行（Parallel）是物理概念，Rio 区分
  - [48:36] “并发是 dealing with many things at once，并行是 doing many things at once”，Rob Pike 的定义
  - [50:23] 做饭的例子：一个人做饭是并发，有帮手才实现并行，吴涛演示
  - [52:47] 在多个抽屉里找黑棋子是 embarrassingly parallel 任务的例子，吴涛说明
- **[1:20:45] 并发模型**
  - [1:21:08] Go 语言采用 CSP（Communicating Sequential Processes）模型，Rio 介绍
  - [1:23:27] 储物箱比喻 CSP：程序只与管理员交互，无需关心内部锁细节，吴涛类比
  - [1:25:50] Actor 模型通过邮箱通信，与 CSP 形成对偶，Rio 比较
  - [1:28:21] Go 的 channel 可缓冲，混合了 Actor 特性，Rio 指出
  - [1:29:38] Actor 模型因每个 Actor 有唯一标识，天然适合分布式系统，吴涛认为
- **[1:33:18] 异步IO**
  - [1:33:47] Q: 当并发模型遇到用户输入等 IO 操作时如何处理？吴涛引出异步话题
  - [1:34:22] Node.js 使用 libuv，Python 有 Tornado，均实现异步 IO，Rio 列举
  - [1:36:06] 做饭中的异步：烧水时切菜，水开后再处理，吴涛再次用做饭类比
  - [1:38:19] 基于回调的异步 IO 导致控制流反转与 callback hell，吴涛指出
  - [1:42:10] 协程（coroutine）可暂停函数并保存上下文，解决回调地狱，Rio 介绍
  - [1:44:33] 进程、线程、协程的开销依次降低，协程最轻量，Rio 比较
- **[1:48:37] 学习语言**
  - [1:50:27] Q: Erlang 语言名称从何而来？Rio 解释来自 Ericsson Language
  - [1:51:53] Erlang 的 OTP 框架用 Supervisor 监控线程，崩溃自动重启，Rio 描述
  - [1:53:43] Google 用普通硬件加容错软件，思路类似 Erlang 的容错哲学，Rio 介绍
  - [1:55:51] 学习 Haskell、Erlang 等小众语言可借鉴其解决特定问题的思想，吴涛认为
- **[1:56:07] 结语**
  - [1:57:15] 做播客帮助吴涛理清原本一知半解的知识，分享学习体验
  - [1:58:31] 听众可对节目内容指正并捐款，吴涛结尾呼吁

## Speakers

- **Rio** (host)
- **吴涛** (host)

## Topics

编程语言

## Mentioned

Apple (company), Google (company), Chromebook Pixel (product), Erlang (product), Go (product), MacBook (product), Node.js (product), Seven Parallelism in Seven Weeks (product), USB Typewriter (product), libuv (product)

## Transcript

### 开场

**吴涛** [0:00]
北美山地事件 ，2006 年 1 月 2 日下午 3:04:05， 您正在收听 IPN Podcast 网络旗下的 IT 技术主题节目 《 内核恐慌 》。 我们号称 "Hardcore"，但也没有干货 ， 想听的人听 ，不想听的人就别听 。

内核恐慌的网址是 ipn.li/kernelpanic， 我们推荐大家使用 Podcast 客户端订阅我们的节目 ； 如果您不知道该用什么客户端 ， 请访问 ipn.li/faq。在录音过程中， 您可以拨通热心电话参与我们的节目 ， 电话号码是 ——

电话号码是 ——

**Rio** [0:36]
差了 。

**吴涛** [0:37]
算了吧 ，0118 999 881 999 119 7253。 我觉得 Lawrence 其实把那个 —— 其实把那个 —— 那个节目里面 ， 就是 《IT Crowd》 里面 ， 唱的音在这边插进来 。

**Rio** [0:51]
好吧 。

**吴涛** [0:53]
Anyway， 呃 ， 如果你非常喜欢我们的节目 ， 或者说不管你是否喜欢我们的节目 ， 你都可以为我们捐款 ， 捐款地址是 ipn.li/kernelpanic/donate，D-O-N-A-T。

呃 ， 捐款的金额随意 ，但是必须是可以被 8 整除的正整数 。OK。

**Rio** [1:13]
等下， 那个地址你用的是 IPN 那个吗 ？ 你也可以用 kernelpanic 那个 .fm 那个地址 。

**吴涛** [1:18]
OK， 我们有了新的域名是 kernelpanic.fm， 所以捐款地址也可以是 —— 对 ， 这不便宜啊 。

**Rio** [1:27]
贵的这个域名。

**吴涛** [1:28]
对 ，因此我们更需要大家捐款 ， 要不要 ——

**Rio** [1:31]
跪求大家捐款 。

**吴涛** [1:32]
是吧 。

**Rio** [1:33]
最低 8 块 ， 上不封顶 。

**吴涛** [1:35]
对 。 捐款地址是 ipn.l- 呃 ，sorry，kernelpanic.fm/donate，D-O-N-A-T。 呃 ， 对 ， 今天是我们的第多少期 ？

**Rio** [1:47]
13。

**吴涛** [1:47]
13 期 ，13 期 ，0x0c。 嗯哼 。 Wait a second, 0x0d。

**Rio** [1:55]
10x—

**吴涛** [1:58]
10 是 A， 对吧 ？11 是 B，14—— 对 ， 所以是 0x0d。13 这个数字不是非常的 ——

**Rio** [2:07]
吉利吗 ？

**吴涛** [2:08]
嗯 ， 好像也 。 我也不知道 ，在欧洲某些国家 ，13 好像是个蛮吉利的数字 。

**Rio** [2:14]
那我 ， 我 —— 因为我们这边没有 13 层那么高的楼 ， 所以我不知道 。 没有 ， 没有办法验证 。

**吴涛** [2:19]
嗯 。

**Rio** [2:22]
大农村 。

**吴涛** [2:23]
大农村 ， 没错 。 哎 ， 你知道加拿大的意思吗 ？Canada。 Canada 是 —— 是当地人的语言吗 ？

**Rio** [2:31]
就是 ， 就是什么 IS， 就是那种什么 ， 就是因纽特人还是什么人的语言里面 ， 就是 Big Village， 大农村的意思 。

**吴涛** [2:39]
OK。

**Rio** [2:41]
倒也贴切 。

**吴涛** [2:42]
嗯 。

**Rio** [2:46]
黑得好 。

### 上期回顾

**吴涛** [2:48]
呃 ， 对 ， 我们上一期请到的幕僚里面 ， 就是我们上一期请到幕僚那期节目里面 ， 我们反复提到了 ， 或我 ， 我反复提到了 How I Met A Modern 里面 ， 然后里面另外一个 ， 除了纽泽西 ，他们也许很喜欢黑的另一个地方就是加拿大 。

**Rio** [3:04]
不是 ， 还有那个地方吧 ， 那个叫 —— 哎 ，Penny 那来那个人叫什么 ？

**吴涛** [3:09]
Penny？

**Rio** [3:10]
啊 ， 那个 Big Bang Theory 里面 Penny 那个老家那个地方来的 。

**吴涛** [3:14]
啊 ， 我不知道 。

**Rio** [3:15]
那个州叫 —— 查一下 。

**吴涛** [3:20]
Penny from—

**Rio** [3:25]
这个时候应该问 Siri 对不对 ？

**吴涛** [3:30]
Penny。

**Rio** [3:39]
Nebraska。

**吴涛** [3:40]
啊 ，Nebraska，OK。

No, I'm from Omaha.

**吴涛** [3:43]
呃 ， 哦 ， 那个 《The Walking Dead》 里面 ， 就是那个行尸走肉 ， 美剧 《 行尸走肉 》 里面有一集也叫 《Nebraska》， 就是讲他们想要去 Nebraska， 然后说那边人少 ， 然后很多枪 ， 然后又是 Flying Oral State， 所以僵尸不会太多 ， 连在这种末日片里面都要被黑一下 。

**Rio** [4:01]
对 ， 太惨了 。 嗯 ， 上期我们请到了幕僚 ， 大神 ， 跟我们 ， 然后我们瞬间多了很多粉丝和 ——

**吴涛** [4:14]
没错 。 你这可能是 —— 对 ， 我们 ， 我们之前觉得可能 《 键盘苟皇 》 那期是比较 ， 比较受欢迎的一期 ，但是现在看来好像这 ， 这已经是一个后无来者的 ——

**Rio** [4:26]
前无古人后无来者的高度了 ， 对吧 ？

**吴涛** [4:29]
对 ， 幕僚这一期真的是 ， 我靠 ， 现在 ， 现在看来真是不管是在微博上还是在 ， 嗯 ，Twitter 上还是在 ， 还是由热情听众 、 热心听众们写的来信里面 ， 这一期都是非常受欢迎 ，而且引起热议的一期 。

**Rio** [4:46]
嗯哼 。 而且你发现没 ， 这一期出现之后我们多了很多女粉丝 。

**吴涛** [4:51]
对 ， 就 ——

**Rio** [4:52]
然后我 ， 我 ， 我挨个点进他们微博去看 ， 都是美女竟然 。

**吴涛** [4:58]
你居然会挨个点进去看人家的微博 ， 你这样对吗 ？

**Rio** [5:01]
我这个也是要关 ， 关 ， 关注粉丝的反馈嘛 ， 对不对 ？ 但我一般是看见头像是美女才点进去看一下 。

**吴涛** [5:08]
这 Kernel Panic 这么高冷的节目都要看脸 ， 这样对吗 ？

**Rio** [5:13]
啊 ？ 我们都不露脸 ， 没有关系 ， 没有关系 。

**吴涛** [5:16]
好吧 。

**Rio** [5:17]
所以 ， 所以 ， 所以看起来还是什么男神的魅力很大哈 。

**吴涛** [5:21]
对 ，而且 ，而且有一个 ，有一个 ，有一个 Twitter， 呃 ，有一个 ，有一条微博说 ， 呃 ， 这一期毕竟都是男神 ， 得有点闷 ， 然后咱们俩就可怜的屈居在 ， 屈居在那个闷里面了 。

**Rio** [5:35]
哎呀 ， 人家还是为了照顾下我们的情绪而已 ，不要太当真 ，不要太当真 。

**吴涛** [5:40]
好了好了 。 对 。其实我们也在酝酿 ， 或者说在 ， 呃 ， 歪歪下将来还会有一期请到 ， 重新请到幕僚 ， 呃 ，不过目前没有一个太 ， 呃 ， 确切的时间表 ，但我们会努力的 。

**Rio** [6:00]
对 。

**吴涛** [6:00]
然后下一期可能会想要谈论一些和数据相关的 ， 和统计学相关的主题吧 。其实我们这边也可以请听众们自告奋勇 ， 如果你觉得你对数据这个话题 ， 或者说对统计学这个话题比较有 ， 比较感兴趣 ，并且可以从和程序相关的角度谈一谈你的看法 ， 那我们也可 ，也非常欢迎你 ， 呃 ， 或者是报名参加我们的节目 ， 或者是为这一个将可能出现的主题写

一些你的看法 。 因为我们现在 ， 嗯 ， 主要是会收到一些 ， 呃 ，feedback， 就是 ， 就是主要是在节目播出之后， 比如说我们今天 ，是今天吧 ， 收到一封 2200 多字的读者来信 ，是 ，是一位微软员工 ， 然后专门 ， 呃 ， 提供了上幕僚这一期的很多反馈 ，但是这些反馈里面有很多我们都觉得其实相当有意义 ，但是 ， 嗯 ， 全文念出来实在是会占用比较长的时间 ， 所以也许

比较好的一点 ， 比较好的一种 ， 嗯 ， 模式是我们告诉听众朋友们下一期 ， 或者说将来会出现的某一期的话题是什么 ， 然后各位听众可以就此写一些感想 ， 然后我们可以在 ， 呃 ， 节目里面 ， 或者是念出来 ， 或者是就其观点做出讨论 ， 我觉得也挺好的 。

**Rio** [7:26]
嗯哼 ， 没错 。 然后我真的很感动啊 ， 真的是 ， 本 ， 本节目开播以来 ， 这也 ， 这不算有史以来最长 ，但是绝对也是较长的那一些少数了 。

**吴涛** [7:39]
对 ，是 。

**Rio** [7:40]
关键是 ， 关键是他说 ，他说他是微软的员工哈 ， 然后我们还这么黑他们 。

**吴涛** [7:47]
对 。 比如以后黑他们 。

**Rio** [7:49]
还坚持下嘴轻一点 ，是真爱 。 我们以后下嘴轻一点 。 特别照顾 ， 特别照顾女 ， 女粉丝的心 ， 那个心情 ， 对不对 ？

男粉丝就 。

**吴涛** [7:59]
微软居然有女粉丝 ， 这个真的不太正常 。 不过想想萧吉杰也是 ， 等等 ， 萧吉杰也是微软粉丝吗 ？

虽然他是微软员工 ，但是萧吉杰是微软粉丝吗 ？

**Rio** [8:08]
嗯 ， 我们可以下期找 ， 想办法请到他来 ， 你可以当面问他 。

**吴涛** [8:13]
好好好 。 你将来一定要有一期请萧吉杰 。

**Rio** [8:16]
嗯哼 。

**吴涛** [8:17]
嗯 ， 对 。 总之我觉得上一期 ， 呃 ， 幕僚这一期到现在还是觉得 ， 怎么说 ， 好像纯只流行 ， 然后膝盖酸软 。

**Rio** [8:27]
上期 。

**吴涛** [8:27]
哈哈哈 。Anyway， 呃 ，其实回应一下上一期的一些 ， 一些没有彻底展开的观点吧 ， 就是其实我后来也想了想上一期提到的一些事情 ， 比如说我觉得 ， 嗯 ， 比如说工具不好用这件事情 ， 嗯 ， 我不知道你怎么觉得 ，但我觉得现在的编程工具要比 10 年前好用太多了 ， 你不觉得吗 ？

### 编程工具

**Rio** [8:53]
我想想 10 年前我在干嘛 。

**吴涛** [8:56]
别这样好吗 ？ 别这样好吗 ？

**Rio** [8:59]
10 年前我刚上大学 ， 嗯 ， 还不怎么啊 ， 然后学的是商科 ，也不怎么写编 ，也不怎么写程序 ， 没感觉 。

**吴涛** [9:08]
好吧 。 但我是觉得现在的编程工具要比 10 年前 ， 就是 2005 年左右 ， 真的好用很多啊 。2005 年的时候 ， 嗯 ，不说别的吧 ， 你写一个最简单的 ， 最最基础的东西 ， 你 ， 你写个网页出来 ， 那个时候哪有什么 WebKit Console 这种东西 ， 就那个时候就用 ——

**Rio** [9:30]
那个就是什么 ， 呃 ， 编辑一下然后刷新页面查看了 。

**吴涛** [9:34]
对啊 ，而且那个时候用的是 Internet Explorer 好吗 ？Internet Explorer 那个时候还没有 ， 没有 Tab 的 ， 就是你 ， 你用 ， 呃 ， 那个时候我是用 Notepad++ 写一个 ， 写 ， 写一个 Markup， 然后在微软 ，在 IE 里面刷新 。

现在呢 。

**Rio** [9:51]
然后去 ， 然后去猜 ， 然后自己头脑中模拟那个什么 DOM 解析器的一步一步猜它为什么会这样 ， 对不对 ？

**吴涛** [9:59]
对 。 而现在 Web Console 是多么好用的一个东西啊 ， 你可以随时去改任何一个页面上的大部分元素 。

**Rio** [10:07]
嗯哼 。

**吴涛** [10:07]
但是除非你再用一些比较二的东西 ， 比如说 ， 呃 ，GW， 呃 ，GWT 这种东西 ， 那 ， 那 ， 那搞出来的东西是真的没有办法在 WebKit Console 里面 debug 的 。

但是如果你徒手写的话 ， 那这些工具真的要比 10 年前好太多了 。

**Rio** [10:23]
对啊 。

**吴涛** [10:24]
呃 ，而且很多语言都 ， 现在很多动态语言 ， 或者说尤其是动态语言 ， 都提供了自己的所谓 REPL， 呃 。

**Rio** [10:33]
呃 ，REPL？

**吴涛** [10:34]
对 ，REPL， 叫 ， 这是什么缩写来着 ？Write。

**Rio** [10:37]
Read、Evaluate、Print Loop。 读入 ， 然后叫什么 ，Evaluate， 中文叫 。

**吴涛** [10:44]
求值 。

**Rio** [10:45]
求值 、 打印 、 循环 。

**吴涛** [10:47]
对 。 当然 REPL 其实并不是一个非常 ， 嗯 ， 新颖的东西 ， 就比如说你说 ， 呃 。

**Rio** [10:56]
我们一开始的时候它就有了啊 。

**吴涛** [10:58]
对 ，而且就哪怕是命令式语言 ，在 Basic 上面其实也是一个 REPL 啊 ， 就在 ， 呃 ，在 Apple II 上面的 Basic 也是一个 REPL。

**Rio** [11:10]
哦 ， 对对对 。

**吴涛** [11:11]
对 ，也是一个 REPL。

**Rio** [11:11]
就是一行一行解析执行 。

**吴涛** [11:12]
对 。 除非你打行号然后再 ， 再打 run， 否则它就是一个 ， 默认就是一个 REPL。

**Rio** [11:19]
嗯哼 。

**吴涛** [11:20]
呃 ，但是现在的 REPL 要比 ， 又要比那个时候的 REPL 要好太多了 。 就不管是 ， 比如说我们有现在像 iPython 这样的非常实用的日常笔记本工具 ， 呃 ，Rubio、Pry，是那个 ，是念 Pry 吧 ，P-R-Y， 就是撬棍的那个词 。

**Rio** [11:43]
哦 。

**吴涛** [11:43]
还是念 Pry。

**Rio** [11:44]
我没怎么用过 。

**吴涛** [11:45]
Pry 吧 。

**Rio** [11:45]
没怎么用 。

**吴涛** [11:46]
对 。 这些 ， 就是这些东西都是支持 ， 比如说你在输入的时候就可以语法高亮 ， 然后， 嗯 ， 甚至你可以把它当成一个 ， 一个包 ， 呃 ， 嵌到你的 ， 嵌到你要想要 debug 的程序里面 ， 然后你在那个地方设置一个 ，以前是要设置一个断点 ， 用 ， 用什么 pydb 之类的 ，而现在你可以直接把 iPython 断在那个地方 ， 然后执行的时候你跳出来一个 iPython 执行环境 ， 你可以随便想干什么都

干什么 。

**Rio** [12:15]
对 。

**吴涛** [12:15]
就 。

**Rio** [12:15]
对 。

**吴涛** [12:17]
然后有 ， 比如说我们之前在苹果的发布会上看到的 Swift 的那个 Playground， 它其实也是一个更为先进的 REPL 吧 ， 就是它 ， 它有所谓的 Live Programming 的 ， 的 ， 的能力 ， 你可以更加直观地看到你写出来的东西是什么 ， 或者说它 ， 它跑起来 ， 它在局部跑起来是一个什么样的过程 ， 这其实都是非常非常方便的一些特性 。

**Rio** [12:43]
嗯哼 。 那就是说 ， 就我们这么过去十几年间 ， 就是在普及用的工具还是在进步吧 ，不过我觉得可能离真正像普通人， 或者是说像幕僚老师这种不喜欢用工 ， 就不太喜欢花时间去学这种工具的人 ，他可能还是有点 ， 呃 ， 困难 。

比如说至少我们在日常用的时候 ， 很多那种 REPL， 它还是有很多限制的嘛 ， 比如你不能做很多事情 ，有时候啊 ，而且对这个环境的 inspection， 就是检查的能力也是有一定的限制的 。

你不像说在 ， 像再早一点 ， 什么像 Smalltalk 那种虚拟机 ， 那叫什么 ，Scroll， 对不对 ？

**吴涛** [13:23]
对 ， 它自带一个核池 ， 核池就是怎么说呢 ，是有点像 IDE，但又不像 ， 都不是 IDE 的这么一个 。

**Rio** [13:29]
对 ， 它的 ， 它的那个好处就是说整个那个 ， 那个整个 ， 就是那个环境 ， 那个操作系统 ， 那个世界 ， 都是可以被 inspection 的 ，而且是可以很方便的语法很统一的规则去 ， 去做它 。

就所以 ， 呃 ， 历史上是确实曾经出现过那种所谓 ， 就哪怕是按现在的观点来看 ， 就是所谓惊为天人的这种工具的设计 ，但是只是因为一些 ， 呃 ， 商业的 ， 或者是这个其他的原因没有流行起来嘛 ， 所以现在我们还是在不断地去朝那个方向演进 ， 呃 ， 虽然还没有达到那个高度而已 。

**吴涛** [14:04]
其实这也是一个很有意思的问题 ， 就是 ， 嗯 ，有时候我们很难说一个成功的事物 ， 就是因为它的技术比较优越 ，而更 。

**Rio** [14:16]
就经常都不是这样子的嘛 ， 特别是在技术界里 ， 我们不是有个说法吗 ， 叫做 worse is better， 就好像经常很多人吐槽说 ， 哎呀 ， 你那个 Linux 这么流行 ，但是你看一下你的底层的设计 ， 很多地方是很不优雅的 ， 很不 unixy 的嘛 ， 对吧 ？

**吴涛** [14:30]
很恶心的 。 但是反过来你说那些优雅的 ， 比较高竿的东西 ， 却又往往流行不起来 ， 比如说 Planary， 就 ， 嗯 ， 甚至不说 Planary 这么比较冷门的东西 ， 编程语言里 ， 编程语言里面也是 ， 基本上是比较流行的语言往往是比较糟糕的语言 。

**Rio** [14:49]
哈哈哈 。

**吴涛** [14:51]
尽管它们 。

**Rio** [14:52]
阴阳黑 。

**吴涛** [14:53]
哈哈哈 。 算了 ， 我们就不举具体的事例了 。

**Rio** [14:56]
OK。

**吴涛** [14:58]
嗯 ， 对 。 然后 ，但是我 ， 我也承认 ， 就是现在的编程工具虽然要比 10 年前好很多 ，但它们仍旧没有能够好到一个 ， 就是怎么说呢 ， 就是造成一个所谓范式转化的地步 ， 就是没有说一个工具是如此好用 ，以至于整个编程界的 ， 嗯 ， 整个编程的方法论都被颠覆了 。

**Rio** [15:24]
对 ， 还没有 ， 还没有出现过这种东西吧 。 就出现 ， 曾经出现过 ，但是没有被保留下来 ， 可以这么讲 。

**吴涛** [15:34]
对 。 呃 ， 就 ， 就好像有一个电影 ，有部电影叫什么 《 剑与行动 》， 呃 ， 里面主角在 ，在编程的时候 ，他编程的方法就是把一大堆方块拖来拖去 ， 然后而且是 ，而且是非常看起来仍同样很复杂 ，但是你会觉得 ， 你会 ， 就是至少观众们会认为这是在编程 ，但在程序员看来这是在搞 ， 这是在解构方块吗 ， 还是怎样 。

呃 ， 如果真的有那样的工具出现的话 ， 那也许是一个非常颠覆性的创新之举 。 呃 ， 到那个时候也许 ， 嗯 ， 幕僚大神们就 ， 就可以比较无障碍地 ， 呃 ， 利用编程工具解决 ， 解决更 ， 怎么说呢 ， 抽象层级更高的问题 ，而不是去 ，而不是去操心这些细枝末节 ， 比如说分号或者是缩进之类的事情 。

**Rio** [16:29]
没错 。 所以觉得 ， 呃 ，有时候我一直在想啊 ，其实可能现在造成现在这种工具比较乱 ， 然后设计也不够优雅的局面 ，是不是有 ， 我有时候在想 ，是不是应该等我们这批人死掉之后， 然后从另外一批人重新来设计 ， 那么一些理念可能会好一点 ， 从娃娃抓起 ， 重新想一下怎么去教小朋友一个比较直观的 ， 呃 ， 或者说更加合理的抽象层级吧 ， 然

后叫他们去 ， 去 ， 逐步去学会一些新的范式 ， 可能会有意思很多 。

**吴涛** [17:03]
对 。 有时候 ， 对 ，有时候我其实刚刚也在想这个问题 ， 就是我想到 ， 嗯 ， 虽然 60 年代的那一批计算机先驱们已经离我们而去了 ，但是我们现在活着的 ， 嗯 ， 计算机先驱们 ， 比如说 Rob Pike，Rob Pike 还是在做 ，在 ， Google 做一线的这种语言开发工作 ，但是我在想说 ， 我们能够和这些人仍旧在同一个时代是一种幸福 ，但是如果再远一点 ， 比如说过个二三十年， 等

这批人去了之后， 那个时候的编程的 ， 的 ， 的地平线会是一个什么样的 ， 什么样的风景呢 ？ 可能会跟现在完全不一样 。

就 ， 就好像那天我做的那个内燃机的比喻 ，也许我们现在用的就是内燃机 ，也许 ，也许过了 20 年电动机出现的时候 ， 编程真的和现在的 ， 和现在我们所熟悉的这些工具 ， 呃 ， 就完全不一样了 。

**Rio** [17:57]
嗯哼 。

**吴涛** [17:58]
这是一种很 ，而且这是一种很难想象的状态 ，也许那个时候我也不知道 ， 三进制计算机 ， 平衡 ， 平衡三进制计算机 。

**Rio** [18:06]
起码的人， 起码的人， 永远 ， 永远不会想到会飞的人是怎么样的一种心态 ， 对不对 ？

**吴涛** [18:11]
对 。 就好像那些 19 世纪初期的科幻画 ， 想 ， 幻想 20 世纪是什么样子 ， 那个时候 ， 想到 20 世纪说每个人都在天上飞 ， 然后天上飞的人会受到天上飞的交警的指挥 ， 可是他 ， 可是他画出来那个会在天上飞的交警身上是一 ， 一 ， 一双翅膀 ，而且还是在 ， 还是在那边吹哨子 。

就 ， 如果现在有什么空中单人的交通工具的话 ， 那我相信去控制这种交通工具的规则肯定不会是吹哨子吧 。

**Rio** [18:49]
哈哈哈 。 音速已经太慢了 。

**吴涛** [18:50]
对 。 所以我们现在所做出的任何想象 ， 可能在那个时候看来都是非常幼稚而可笑的 。

**Rio** [18:56]
嗯哼 。

**吴涛** [18:57]
但这仍旧拦不住我们去想 ， 对吧 ？

**Rio** [19:00]
对 。 好吧 ， 那个什么 ， 上期的 follow up 就做到这里哈 。 我们 。

**吴涛** [19:06]
哎 ，其实还有一个 ， 就是 ， 嗯 ， 呃 ， 上期幕僚说到 ， 呃 ， 比如说那个有些语言非常要求你什么注意分号 、 缩进啊 、 大小写啊之类的 ，他有没有说大小写我不记得 ，但是我前两天看了看那个 Nim 语言 ， 就是新出的那个 ， 之前叫 Nimrod 的 ， 然后现在叫 Nim 的语言 。

**Rio** [19:26]
嗯哼 。

**吴涛** [19:27]
呃 ， 这个语言有一很有趣的一点 ， 就是它 ， 嗯 ， 区分一个标识符的时候 ， 只区分第一个字母是不是大小写 ， 后面是无关的 ，而且带下划线也是无关的 。

**Rio** [19:42]
这有什么好处呢 ？

**吴涛** [19:43]
就是它 ， 它列举的好处是 ， 呃 ， 比如说你 ， 你的 ， 你写一个 ， 呃 ， 写一个程序要用到别人的库 ， 别人的库有一个它自己的变量 convention， 然后或者说 ， 呃 ， 函数 convention， 当你要调用那些函数的时候 ， 你可以利用自己的 convention，因为也许它是用下划线做分格 ， 分隔符的 ，而你喜欢 camelCase， 那你可以在你的程序里面写 camelCase， 呃 ， 程 ， 那个编译器会自己去猜真正的标识符是什么 。

就我觉得这是一个很有 ， 很有意思的 ， 很有意思的 feature。

**Rio** [20:21]
真是个恶趣味啊 。

**吴涛** [20:23]
对 。 但可能从另外一个角度讲 ， 它也是在试 ， 试图解决这样一种就是 ， 呃 ， 你可以再去忽略另外一个细节 ， 就是你不用去永远去刻意地注意大小写要一致 ， 然后你可以借用这个 feature 来保证自己的编程风格在内部是一致的 。

**Rio** [20:42]
嗯哼 。 嗯 ， 说一下这周发生的一些小新闻吧 。

### 苹果发布

**吴涛** [20:47]
嗯 。

**Rio** [20:47]
然后那个 ， 你也看了那个苹果发布会了哈 ？

**吴涛** [20:50]
好呀 。

**Rio** [20:51]
那我们之前专门讨论过那个谣传中的新的 MacBook， 呃 ， 它其实不是 Air 了 ， 它就是 MacBook， 然后你觉得 。

**吴涛** [20:59]
对 ，其实这很有 ， 很有 ， 很有趣的一点 ， 为什么 MacBook Air 还叫 MacBook Air， 然后新的这个更薄更 Air 的还叫 ， 反而叫 MacBook。

**Rio** [21:07]
哎 ， 我 ， 我 ， 我后来是这么理解的 ， 就是因为 ， 你有把现在 ， 就现在那个 MacBook Pro 它也变得很薄了嘛 ， 所以以后就不分有这个 Air 这概念了 ， 就薄是一个必然的属性 ， 然后只区分是否专业 ， 所以 MacBook Air 那个产品线可能过几年， 过两三年就直接就没了 。

**吴涛** [21:26]
消失了 。OK。

**Rio** [21:27]
对 。 就只有 MacBook 和 MacBook Pro 这样的两个分野 ， 我觉得这样其实是更清晰的一个结构嘛 。

**吴涛** [21:33]
然后如果你要比 MacBook 更薄的东西 ， 就只能去买 iPad 了 。

**Rio** [21:38]
哎 ， 对 ， 没错 。

**吴涛** [21:39]
OK。

**Rio** [21:40]
嗯 。 所以最 ， 最重要的一件事情是 escape 键没有动 。

**吴涛** [21:47]
对 。 我觉得他们也应该是内部顶住了巨大的压力 。

**Rio** [21:51]
不 ， 我们先不确定之前那个 ， 那个图上面那个 escape 键就是真的有原型机长那样吗 ？ 其实是挺值得怀疑的 。

**吴涛** [21:59]
好吧 ， 说的也是 。 也有可能内部从来没有出现过一个 escape 在这么 ，在这么让人天怒人怨的地方 。

**Rio** [22:06]
对 ， 就可能那个 ， 那个谁画图的时候不小心就画成那样了而已 。 不过不管如何 ，escape 键的位置没变 ，而且还变大了 ， 这个是挺好的一件事 。

因为你用过那个 11 寸的 MacBook Air 吗 ？

**吴涛** [22:20]
嗯 ， 用过一次 ， 就是我有一次借前公司的老板的那个办公电脑出过一次差 ，但 。

**Rio** [22:28]
你们 ， 你们公司已经这么惨 ， 还要借老板的电脑出差 ？ 好 。

**吴涛** [22:31]
因为我自己的电脑 。

**Rio** [22:32]
听起来好心酸 。

**吴涛** [22:33]
太重了 。

**Rio** [22:33]
OK。

**吴涛** [22:35]
我觉得我不是很喜欢 MacBook Air， 就当然可能主要也是因为就是屏幕实在是太小了 。

**Rio** [22:42]
啊 ，11 寸的确实很小 。

**吴涛** [22:43]
13 寸的还是很小 ， 我觉得 。

**Rio** [22:45]
它边框也比较大嘛 。

**吴涛** [22:47]
对 。

**Rio** [22:48]
所以你会觉得挺糟糕的 。 呃 ，但特别 ， 特别 11 寸那个 ， 那个 escape 键特别小 ，因为它那个大概半高 ，不 ，1/3 高的那个键吧 ， 呃 ， 然后而且还那么小一坨 ， 然后现在那个 MacBook 上这个 escape 键变得很长嘛 ， 然后我们作为一个 Vim 党 ， 这件事什么 ， 福音啊 。

**吴涛** [23:08]
对 。 所以 ， 所以你是要买一台 ？ 如果听上次 ， 上次 IT 公论的印象没错的话 。

**Rio** [23:15]
OK。

**吴涛** [23:16]
嗯哼 。

**Rio** [23:17]
因为我老婆那台她要换嘛 ， 她要给她买一台 ， 顺便我玩一下， 到时候假设我要出门做点什么事情 ， 我就拿她那台去好了 。

**吴涛** [23:25]
OK。

**Rio** [23:25]
便携 。

**吴涛** [23:26]
所以 ，OK。 这就是顺便玩一下的意思 ， 就是 80% 的时间是你在用 。

**Rio** [23:31]
没 ， 没 ， 没 。 那个性能不太够嘛 ， 它那个最高 ， 就内存是固定的 8G，不能再扩张了嘛 。

**吴涛** [23:36]
对 ， 这是比较一个蛋疼的一点 ， 就是 8G 真的不是很够 。

**Rio** [23:41]
因为 ， 因为这件事情其实还是挺麻烦的 。 现在你看一下我们跑的很多软件的 ， 特别是 64 位之后啊 ， 那些很多软件的体积是就越来越大了 ，而且现在开个网页动不动就几百 ， 一个 Tab 啊 ， 就几百兆上一个 G 的 。

所以还是 8G， 你要再开虚拟机的话 ， 就肯定是不太 ，有点捉襟见肘吧 ， 至少 。

**吴涛** [24:02]
对 。

**Rio** [24:03]
嗯 。 你那台 ， 你那台是 ， 你那台是 16 的吗 ？

**吴涛** [24:07]
我现在这台是 16 的 ， 对 。

**Rio** [24:09]
OK， 我也是 16 的 。 所以现在就作为一个开发者的话 ， 可能还是要 16 才 ， 才至少够吧 。

**吴涛** [24:15]
当然现在可能主要瓶颈不是在内存上面 ， 就有时候跑一些比较大的游戏会是 ， 会风扇狂转 ，但 。

**Rio** [24:23]
它那个没有风扇呗 。

**吴涛** [24:24]
不是内存的问题 。 对 ， 我是说我现在这台 。

**Rio** [24:28]
OK，OK。

**吴涛** [24:28]
如果买新的 MacBook 应该就很多游戏又不能玩了 。

**Rio** [24:32]
不知道 ， 它那款性能现在还没出来 。 昨天我看了一下那个有网上有测评 ， 呃 ， 联想出了一款 ， 就出 ， 出了一款那个 ， 就那个什么 ， 它那种 ， 联想不是有个本子可以变成平板用的那种笔记本吗 ？

叫什么本来的 ，Convert Tablet 之类的 。 然后它用的那个处理器我看了一下性能和那个参数 ， 应该是和 ， 呃 ， 那个 MacBook， 就是新款那个 MacBook 里面那款是差不多的 。

然后我看了一下它在那个测评的性能 ，其实是跟 14 款的 MacBook Air 是差不多的 ， 我觉得还凑合了 ， 就其实很多时候已经够用了 。

就只要你不是经常要编译什么编译 Swift 的 ， 的代码的话 ， 你只是做一些 ， 比如说像我用 Go 的话 ， 就编译很快嘛 ， 就无所谓 。

然后你说做 Web 开发都是动态语言 ， 没有这个编译过程 ， 那也无所谓 。 所以 ， 呃 ， 我觉得性能可能对大多数情况下也是 ，也是凑合够了 。

**吴涛** [25:27]
好吧 ， 我觉得可能做 iOS 开发还是有点够呛了 。

**Rio** [25:31]
屏幕太小了嘛 。

**吴涛** [25:33]
主要 ， 呃 ， 我觉得 iOS 开发跑那个模拟器的时候 ，其实还是挺 ， 挺吃力的 。

**Rio** [25:40]
挺费劲是吧 ？

**吴涛** [25:40]
对 。

**Rio** [25:40]
嗯 ， 没错 。 而且他们现在不是说这个事儿吗 ？ 就是 ， 呃 ，因为现在不是所有的 iOS 都是所谓的 Red Team 的分辨率嘛 ， 就两倍的 。

那么你要在屏幕上真实还原 1:1 的话 ， 你的屏幕要比那个大嘛 。

**吴涛** [25:53]
对 。

**Rio** [25:53]
那现在如果你屏幕那么小的话 ， 就没有办法很好的还原 ， 它就装不 ， 模拟器装不下嘛 ， 只能缩放 ， 就不是太好 。

**吴涛** [26:00]
对 。 但是我相信现在也有很多开发者就是他 ， 如果他真的要跑的话 ，他就不在模拟器上跑了 ， 直接接设备 。

**Rio** [26:07]
接上真机嘛 。

**吴涛** [26:08]
对 。 也是 。

**Rio** [26:09]
那个传输好像还是比较 ， 就你那个 ， 就是那个 cycle 还是比较长 ， 你要传到那个 iOS 设备上去 ， 然后你要马上看结果 ， 中间还是要等那么可能一两分钟吧 ， 我估计 。

**吴涛** [26:21]
呃 ， 我的经历还好吧 ， 我觉得 。 就可能要比在虚拟机里面 ， 呃 ， 快那么 ， 慢那么最多 20 秒吧 ， 我觉得还是可以忍受的 。

**Rio** [26:34]
那也是很大的这个损耗了呀 。

**吴涛** [26:37]
不 ，但到你到后期的时候 ， 我觉得大部分人可能会 ， 就怎么说呢 ， 就回到那个 ， 回到我们之前讨论的 Repo，在没有 Repo 的时代 ， 你可能要用头脑去模拟那个机器跑出来什么样子 。

**Rio** [26:53]
脑子里面想是不是 。

**吴涛** [26:54]
对 。 我觉得到后期 iOS 开发 ，其实很多人都是 ， 呃 ， 会花相对长的时间在写 ， 然后真正看 ， 看效果的时间可能只有开发时间的 10% 不到 。

但除非你在 ，但除非你在 debug，debug 的话 ， 那就是另 ， 那要另说了 。

**Rio** [27:13]
啊 ， 对对 ， 没错 。

**吴涛** [27:16]
对 。

**Rio** [27:17]
嗯 ， 这个新款的本还有一个挺大的事儿 ，是它那个键盘的轴不一样了 。

**吴涛** [27:23]
对 。

**Rio** [27:23]
蝴蝶轴 。

**吴涛** [27:24]
蝴蝶轴 。

**Rio** [27:24]
什么概念 ？ 你有概念吗 ？

**吴涛** [27:26]
我其实也没有很看懂 。

**Rio** [27:29]
就这个蝴蝶轴它是这 ， 这次才新发明 ， 之前是没有这个 ， 这种机制的是吧 ？ 就没有 。

**吴涛** [27:35]
之前是只有剪刀脚的 ， 对吧 ？

**Rio** [27:37]
不 ， 我说苹果上就在其他人有用过这种所谓蝴蝶轴 。

**吴涛** [27:40]
从来没有 ， 就从来没有见过 。

**Rio** [27:41]
因为我看他说的是应该是他们自己新发明的一种 ， 一种那个键盘轴的机制吧 。

**吴涛** [27:48]
对 。

**Rio** [27:48]
然后他说这个有个好处 ， 就是说剪刀脚有个问题 ， 就是说如果你 ， 它会不平稳嘛 ， 就是你说你按 ， 你按一个键 ， 键的一个角落 ， 它会斜着下去 ，有时候会触发不到 。

**吴涛** [27:59]
对 。

**Rio** [28:00]
哦 ， 虽然我自己从来没有意识到这种情况 ，但是我不知道这个是很常见的现象吗 ？ 还是怎样 ？

**吴涛** [28:05]
就是你 ， 你按那 ， 你在按苹果的键盘上的一个键的时候 ， 你会明显感觉到让你按的时候那个键 ， 键是随着你按的那一脚先开始下线 ， 然后其他部分一起才跟着下线的嘛 。

**Rio** [28:17]
但是不应该按你按那个键的中心位置吗 ？ 你为什么会按它的边角呢 ？

**吴涛** [28:22]
呃 ， 我倒是觉得在大部分时候你是不可能完 ， 就正儿八经按到它的中心位置这样 。

**Rio** [28:30]
OK。 对 ， 我 ，因为我自己从来没有留意到我有 ， 有发出现过这种 ， 啊 ，因为按到那个 ， 那个剪刀脚的某一个边 ，而不是中心的位置触发不了的情况 ， 所以我还挺好奇他在发布会说这是 。

**吴涛** [28:43]
触发不了是肯定不会的 ，但是剪刀脚所造成的问题就是你按那个键的时候 ， 你会觉得键 ， 怎么说呢 ， 我觉得这个 ， 这个区别是只有你在按上去的时候才会感觉到的 。

就是你按一个 ， 比如说我在 ， 我在按 ， 按那个 HHKB 的时候 ， 按一个键 ， 这个键是本身是不会晃动的 ， 对吧 ？

就是我按这个键的最左上角 ， 整个键会随着我的手指一起下线 ，但是你再按一个剪 ， 呃 ， 剪刀脚的时候 ， 那个键的左上角会先下线 ， 然后其他部分才跟着下线 。

**Rio** [29:20]
啊 ， 没错 ，是这样的 。

**吴涛** [29:21]
就这个键是会有一定的所谓 ， 呃 。

**Rio** [29:25]
摇晃 ， 对吧 ？

**吴涛** [29:25]
我 ， 对 ，wobbling space， 就是它 ， 它有 ， 它会有一种不稳的感觉 。 但是 ，但是我相信它蝴蝶脚所要解决的问题就是你不会再有这种感觉了 ， 这个键就是实的 ， 然后你按下去一点 ， 整个键会跟着一起下线 。

**Rio** [29:38]
嗯哼 。他们那个现场去测 ， 就是试用过那款新的 MacBook 的那个键盘的时候 ， 都说那个键程非常非常短嘛 ，因为它那个整个厚度降低了 ，而且它这个蝴蝶轴的这个本来的一个设计初衷就是为了减低这个厚度嘛 ， 对吧 ？

高度 。 那我不太清楚这种键程极短的情况下， 对编程的时候的打字的手感会有什么变化 。

**吴涛** [30:03]
呃 。

**Rio** [30:04]
你 ， 你 ， 你喜欢长 ， 长键程还是短键程的按键 ？ 那个键盘 。

**吴涛** [30:10]
其实我不怎么挑 ，但我觉得 。

**Rio** [30:12]
不怎么挑哈 。

**吴涛** [30:13]
对 ，但我觉得就是在用触摸板的时候 ， 呃 ， 你可以理解为这个键程是 0， 对吧 ？ 那 ， 呃 ， 我不知道 ， 就是也许在配了触摸板的笔记本电脑上， 按一个键程比较短的键 ， 呃 ，其感觉是不是至少要比 iPad 好了 ？

就是你至少是有一点点键程的嘛 。 你在 iPad 上，iPad 上用 ， 按那个虚拟键盘的时候手感是非常差的 ， 对吧 ？

**Rio** [30:42]
那虚拟键盘手感差一个主要是有几个原因吧 ？ 不光是它没有键程这个 ，因为主要是一个是没有触觉的分隔 ， 你不知道你按到哪个键了吗 ？

你不 ， 我不看的话 。

**吴涛** [30:51]
对 。

**Rio** [30:52]
然后第二个是 。

**吴涛** [30:52]
就是因为零键程 ， 所以才没有分隔 ，不是吗 ？ 就是我的意思是 ， 这两个其实是一回事儿 。

**Rio** [30:58]
啊 ， 你说这个 ， 这没有突出 ， 然后也没有下线 。

**吴涛** [31:01]
对 。

**Rio** [31:02]
不 ， 就算 ， 就算是零键程的话 ， 它也是可以有分隔的呀 。 就是 ， 呃 ， 我 ， 我不知道你有没有用过那个微软那个 Surface， 它不是有两款键盘吗 ？

一款是所谓的 ， 呃 ， 叫什么 ？Touch Color 吧 。

**吴涛** [31:15]
对 ， 就是那个薄膜键盘嘛 。

**Rio** [31:17]
呃 ， 它不是一个 ， 就是它们 ， 它是这个 ， 那个就是有分隔但是无键程的一个键盘 。 就你其实按的是一个 ， 对 ， 是一个平板 。

然后它还有一款那个叫做 Type Cover 吧 ， 我记得 。 然后我是用过 ， 那个 ， 那个键程也蛮短的 。 然后我 ， 我两款都试了一下， 都感觉不是很好 。

就键程短这件事情本身是不是太好的 ， 就一切情况相同的情况下哈 。

**吴涛** [31:40]
OK。

**Rio** [31:41]
因为你就没有办法 ， 啊 ， 就有时候你可能会 ， 会觉得不确定嘛 ， 就按下去没有 。 我觉得可能会这样 ， 会是这个原因 。

但是他们说这个 ， 这个蝴蝶轴的这个有些其他的好处 ， 比如说它不会左右乱晃啊 ， 然后它这个打字也很 ， 呃 ， 就是 ， 就他们说那个手感挺 ， 挺特别的 。

我现在也没有打过 ， 我不知道到底是个什么手感 ， 我想 ， 很想去试一下 。 但我又在想 ，其实键程短反而不是应该能帮助你长时间打字吗 ？

这样力 ， 用力会比较小是不是 ？

**吴涛** [32:15]
这个我觉得可能最终省下来的力也只有一点点 。

**Rio** [32:21]
一牛 。 打了一针 。

**吴涛** [32:23]
就是可能省了 ， 省了一牛的力 。

**Rio** [32:25]
对 。

**吴涛** [32:28]
但我觉得这个键程可能更多带来的还是 ， 还是 ， 还是触觉 ， 触感上 ，而真正的省力什么的都是 ， 嗯 ， 非常浮云的东西 。

**Rio** [32:38]
嗯哼 。

**吴涛** [32:38]
对 。 反过来说 ， 你可能你会觉得也许喜欢长键程的人可以去用一个 ， 就前两天在推特上看到的 USB Typewriter。

**Rio** [32:49]
打字转 USB 接口 ， 然后接电脑上打是吧 ？

**吴涛** [32:53]
对 。 我觉得这个 ， 这个实际上是太怀旧了 。 就是你可以去 ， 你可以选择直接从它的网站上买一台已经转化好的 Typewriter。

就它是货真价实的打字机 ， 然后你可以把这个打字机接到 。

**Rio** [33:05]
机械式的打字机 。

**吴涛** [33:06]
对 ， 机械式的打字机接到你的 ， 呃 ，USB 口上， 然后把打字机当键盘来用 。

**Rio** [33:12]
它那个原理是什么 ？ 它是探测那个机械键的位移 ， 然后转成 USB 电信号吗 ？

**吴涛** [33:18]
对 。其实就是如果你去看它的那个 Converter Kit 的话 ， 那个 ， 就是如果你直接从它网站上买的比较贵 ， 可能要 599 还是 699 美元一台 ，但你可以买另外一个 Kit， 这个 Kit 就 99 美元 ， 然后里面有一大堆触板 ， 就是一个比较长条像梳子一样的东西 ， 呃 ， 和一个很小的 ， 我不 ， 应该不是 Arduino， 是一个他们自己做的一个 IC 板 。

你把那个长条的梳子一样的背板贴到 ， 呃 ， 机械打字机的后面 。

**Rio** [33:49]
嗯哼 。

**吴涛** [33:50]
然后再把那个 IC 电路塞在打字机的内部 ， 然后你就可以把它转化成一个 USB 打字机了 。 就其实它就是去探测那个 ，因为你在按下一个打字机上面的键的时候 ， 它后面会有一个东西抬起来嘛 ， 然后就它就 ， 它会去感 ， 感应是哪个键抬起来了 。

**Rio** [34:10]
哦 ，OK。

**吴涛** [34:11]
然后把它转化为键盘性能 。

**Rio** [34:13]
对应的那个键按键 。

**吴涛** [34:15]
对 。

**Rio** [34:15]
这也是挺 。 但它其实那个很累的嘛 ， 打机械 ， 对吧 ？ 机械 ， 机械打字机的那个按键是很费力的 。

**吴涛** [34:22]
对啊 。 就我小时候用打字机打英语作业的时候 ， 就每天晚上打完了手指会疼的 ， 真的 。 那个时候小孩手也小嘛 ， 就 ，而且那个时候我指法也不好 ， 对 ， 只能用食指和中指在按 。

然后有些字母如果你用 ， 让那个 ， 让那个时候我去用小指 ， 用小指去按的话 ， 永远是虚的 ， 比如说 P 啊之类的 ，P、Q 永远是虚的 。

**Rio** [34:44]
嗯哼 。

**吴涛** [34:45]
对 。

**Rio** [34:46]
这也是一种恶趣味 。

**吴涛** [34:49]
对 。 就这叫什么 ， 蒸汽朋克 。

**Rio** [34:52]
机械朋克 。

**吴涛** [34:53]
机械朋克打字机 ， 机械朋克键盘 。

**Rio** [34:55]
嗯 。 呃 ， 说到这个笔记 ， 这个程序员用的笔记本啊 ， 呃 ， 前两天 Google， 就是应该不是前两天 ， 就是苹果发布那个新款 MacBook 之后， 第二天 Google 也发布了这个新款的 Chromebook Pixel， 就是它那款 ， 呃 ， 虽然就官方配置是只能用上网的一个笔记本 ，但是它的整个配置还是不错的 ，有一个高分屏 ， 然后也是 13 寸 ， 一个方头方脑的一个设计吧 。

**吴涛** [35:21]
嗯 。

**Rio** [35:22]
然后我知道很多人就是 Linux 用户 ，他会选这个 ， 然后他装那个 ， 上面有一个这种 ， 一种软件叫做 Chromtone 吧 ， 好像是 ， 就可以在上面 ， 呃 ，在一个类似于这个 Container 的环境里面跑一个其他内核的 ， 呃 ，不叫其他内核 ， 就其他的这个 Linux 的发行版 ， 比如说 Chromtone 啊之类的 。

然后这样的话就有很多好处啊 ，因为 Chromebook 它本身是一个类似于 ， 啊 ，iOS 的设计嘛 ， 就整个它是沙盒机制的 ， 然后你没有办法去更改系统的东西 ， 就安全性是有保 ，有保障的 。

然后你在 ，在那个 Container 里面再跑一个 Linux 发行版 ， 你就弄坏了再删掉重新来一个就好了 。 就很多人会选择这种方式来做 。

**吴涛** [36:03]
是 。 它那个本的唯一的问题就是存储空间太小了 ， 它最大只有 64G 的 SSD。

**Rio** [36:12]
对 。 我觉得我也不知道 ， 你见过身边的人在用 Chromebook 吗 ？ 我为什么我总有一种感觉就是它是一个怎么 somehow 叫好不叫错的产品 。

**吴涛** [36:22]
我没有见过有人自己花钱买它 ， 然后 ，但不过我有个朋友 ，他是前年， 去年， 前年， 前年去那个 Google I/O 的时候 ， 那年不是 Google 每 ， 给去参会的时候每个人送了一台吗 ？

就是那个第一代的 Chromebook Pixel， 然后他 ，他就拿了一台回来 ， 我玩了一下 。 就整个 ， 整个做工和工艺还是不错的 ， 我觉得 。

但是就是能做的事情感觉挺有限的 。

**Rio** [36:45]
OK。

**吴涛** [36:46]
啊 ，因为它那个空间确实比较小 。 啊 ， 它那个是带那个 LTE 还是 4G 网络的 ？ 对 ， 它可以插那个 SIM 卡 ， 这 ， 这点比较有意思 。

**Rio** [36:55]
嗯 。

**吴涛** [36:56]
对 。 就是其实我之前在想说 ， 呃 ，MacBook， 新的 MacBook 为什么不能直接内置 LTE Modem？

**Rio** [37:06]
呃 。

**吴涛** [37:07]
就因为它那个轻薄的程 ， 它那个轻薄的程度其实已经非常适合就是带着到处跑 ，但是带着到处跑有个问题就是在没有网络的地方 ， 比如说它那个宣传广告里面呢 ，有一个 ，有一个女孩 ， 呃 ， 拿着它盘腿坐在一个 ， 呃 ， 公园旁边的长椅上， 然后我就想说它的网从哪来 ？

**Rio** [37:26]
哈哈哈 。 哎 ， 那个苹果的解决方案是说你只要有手机在旁边 ， 可以通过无线的连接一个热点 。

**吴涛** [37:32]
接着来 。

**Rio** [37:33]
对对 。 它可以做一个这个 。

**吴涛** [37:36]
好吧 。

**Rio** [37:36]
我觉得还可以吧 。 因为其实你如果每一个设备都做一个 SIM 卡的话 ， 你每个月的这个交给运营商的月费还是蛮多的 。

就如果是偶尔的 ，有这种场合才使用的话 ， 这样也没什么不好啊 。 之前用做那个 Tethering 还比较 ， 啊 ， 麻烦 ， 你要先配 ，在手机上打开 ， 然后你在电脑上连接一下 。

现在自从那个 Yosemite 里面不是你可以直接 ， 就只要你手 ， 手机在旁边 ， 你点那个 Wi-Fi 的 logo 里面就可以很方便的有一个选项可以直接通过你的手机 ， 呃 ，iPhone Tethering 嘛 。

所以我觉得还好吧 。 而且其实现在就出门你要真的静下来办公 ， 那除非你是去什么公园里面再说哈 ， 就是如果你是什么咖啡馆啊 ， 就有 Wi-Fi 的地方还是太多了吧 。

**吴涛** [38:19]
说的也是 。

**Rio** [38:20]
我 ， 我感觉是这样子起码 。

**吴涛** [38:23]
你有 ever 带着一个笔记本出去办公这种事情吗 ？ 就是你觉得家里太憋或者是外面阳光真好 ， 想要一边写程序一边享受阳光之类的 ， 你 ， 你做这种事情吗 ？

**Rio** [38:35]
有啊 。 夏 ， 夏天的时候我经常带出去在海边 ，因为我们这 ， 我们这 ， 我这个地方就是在靠海嘛 ， 我家离这个大西洋的直线距离可能只有两 ， 两三公里的样子 。

啊 ， 然后我就开 ， 开车开到海边 ， 找个这种稍微 ， 啊 ， 就是那个视线比较好的地方 ， 我就躺 ， 就坐在那个 ， 那个 ， 那个副驾的位置上， 把那个躺 ， 把那个椅子往后折 ， 然后在那里办公 。

**吴涛** [38:58]
就是听着 ， 听 ， 聆听着拍案的怒涛 ， 然后 。

**Rio** [39:02]
我们这里没有怒涛 ， 只有小浪 。

**吴涛** [39:04]
哈哈 。 好吧 。 看着大西洋的浑浊海浪 。

**Rio** [39:07]
大西洋很蓝的 ， 谢谢 。

**吴涛** [39:09]
不像太平洋 。

**Rio** [39:11]
太平洋是很浑浊的 。

**吴涛** [39:13]
太平洋更蓝吧 ， 应该 。

**Rio** [39:14]
我不知道 。 我 ， 我之前在 ，在 ， 就起码在中国的海岸线上看到的太平洋都是挺黄浑浊的 。

**吴涛** [39:22]
那是因为中国的 ， 呃 ， 就是河流 。

**Rio** [39:26]
浅 。

**吴涛** [39:26]
不对 ， 那边的海比较浅 ， 你像渤海有 ， 我们家门口的渤海有时候会冻上来 ， 就浅到这个地步 。

**Rio** [39:32]
OK。

**吴涛** [39:34]
蓝海其实是 ， 就是足够深的地方都是蓝色的 。 这个没什么 。

**Rio** [39:37]
那边可能就是很深的 ， 我去看都是一望无际那种 。 就之前是照片上看到的那种蓝 ， 现在就是我们家旁边的这种蓝 。

**吴涛** [39:44]
OK。

**Rio** [39:45]
啊 。

**吴涛** [39:46]
好吧 。 我 ， 我 ， 我好像我很少干这种事情 ， 就是带着一个笔记本出去办公 。 我觉得 。

**Rio** [39:52]
哎 ， 之前我不是看到有一个德国人 ，他说他都不要那个 ，他是做那个 ， 好像开发那种 ，他是在那种就是主机上， 不是 ，不是主机 ， 就是服务器上开发那种科学计算的应用的人哈 。他都直接不要笔记本了 ，他就带个 iPad， 然后带个蓝牙键盘出门 ， 然后 iPad 有那个什么 LTE，有 4G 嘛 。他就在那个什么公园里面找个 ， 找个凳子坐上， 然后就在那公园不是有长椅那种

木凳 ， 木凳嘛 ， 然后他就把那个拿出来 ， 然后通过 LTE 上网 ，他反正只需要那个 SSH 就过去 ， 所有软件都可以在那个服务器上有嘛 。

**吴涛** [40:28]
呃 ， 它如果只是纯 Console 下面编程的话 ， 这样的确是可取的 。

**Rio** [40:34]
嗯哼 。

**吴涛** [40:34]
但你只要稍微接触到 ， 接触到任何非 Console 的东西 ， 那 iPad 直接就废了 ， 我觉得 。

**Rio** [40:41]
对 。 你要在本地做事情 ， 那肯定是不 ， 不可取的 。

**吴涛** [40:44]
除非你要 ， 除非你现在 iPad 上面有 Xwindow 的 ，Xwindow 的 ， 的 ， 的客户端吗 ？ 没有吧 ？

**Rio** [40:51]
我不太清楚 ，不过有那个 ，有那个叫什么 。

**吴涛** [40:54]
Remote VNC。

**Rio** [40:55]
Remote VNC， 对 ，VNC 的这种东西 。

**吴涛** [40:58]
然后鼠标怎么办 ？

**Rio** [41:00]
呃 ， 就是你用点屏幕咯 。

你要用鼠标肯定就输了 。

**吴涛** [41:08]
听起来有点蛋疼 。 或者用纯 ， 纯键盘的窗口管理器应该也可以 。

**Rio** [41:14]
对 。 你不是反正 Vim 大部分的时候都用那个 Vim 的 KBandy 吗 ？ 应该也差不多合适了 ， 我觉得 。

**吴涛** [41:20]
嗯 。 好吧 ， 下次可以试试 。

**Rio** [41:23]
嗯哼哼 。

**吴涛** [41:24]
我其实 。

**Rio** [41:25]
不 ， 你试试吧 ， 你没有吧 ？

**吴涛** [41:26]
对 。 我是一个 ， 就我觉得如果出门的话就不要办公 ， 如果办公的话就不要出门 。

**Rio** [41:31]
那你想换个环境散散心怎么办 ？

**吴涛** [41:33]
那就不办公呀 ， 就想散心的时候散心 。 就那 ， 那 ， 那什么 ， 叫什么李大超的那篇文章什么玩 ， 玩就玩个痛快 ， 学就学个舒服的 。

**Rio** [41:45]
哈哈哈 。

**吴涛** [41:45]
等等 ，不是学就学个舒服 ， 学就学个什么来着 ， 然后玩就玩个痛快 。

**Rio** [41:50]
OK。

**吴涛** [41:50]
就该 ， 该干嘛的 。

**Rio** [41:52]
就是玩干嘛的 。

**吴涛** [41:52]
Hard play hard 嘛 。

**Rio** [41:53]
对 。

**吴涛** [41:54]
就不要又想 ， 又想轻松 ， 又想 ， 啊 ， 办 ， 要办公就站着 ， 然后敲一台机械键盘 ， 用一个 ， 用一台 Power Mac， 然后要出去就什么都不 ， 什么都不要带 。

**Rio** [42:08]
那如果你是这种人的话 ， 你为什么要买一个笔记本呢 ？

**吴涛** [42:12]
因为我并不具备 ， 尚不具备 ， 呃 ， 一个可以装 Power Mac 的办公室 ， 我觉得 。

**Rio** [42:21]
不不 ， 你可以用那个什么 iMac 之类的呀 。

**吴涛** [42:25]
呃 ， 我之前的确是在 iMac 和 Power， 呃 ，不是 ， 和 ， 嗯 ，MBP 之间 ， 呃 ， 犹豫了一阵子 。 因为那个时候我正要从一个城市搬到另外一个城市嘛 ， 就是考虑到自己可能即将要换工作 。

**Rio** [42:41]
搬家 。

**吴涛** [42:41]
对 。

**Rio** [42:42]
对 。

**吴涛** [42:42]
然后现在 。

**Rio** [42:43]
是一个挺麻烦的事情 。

**吴涛** [42:44]
对 。 然后那个时候正考虑说如果搬到女朋友那边去住 ， 然后可能暂时不会有一个办公室 。 事实上我现在的确没有一个办公室 ， 所以可能还是 ， 嗯 ， 嗯 ，有一台笔记本比较方便 。

**Rio** [42:56]
就起码它在整个体积上还是可以小一些 。

**吴涛** [42:59]
对 。

**Rio** [42:59]
然后拿走的话也方便一点 。

**吴涛** [43:01]
对 。

**Rio** [43:02]
其实我也 ， 我也是这样 ， 我的笔记本大部分都是 ， 就是放在桌上， 然后接显示器 ， 然后插各种线 ， 就当桌面机 ， 就什么 Desktop replacement 嘛 。

**吴涛** [43:13]
对 。 因为就我觉得 MacBook Pro 其实有一点就是 ， 如果你出去旅游的时候要带它还是不带它呢 ？ 就 ， 嗯 。

**Rio** [43:21]
不带它显然 。

**吴涛** [43:23]
对啊 。 但如果我有一台 iMac 和一台新的那个 MacBook 的话 ， 那我可能会毫不犹豫的选择带上 。

**Rio** [43:29]
对 ，因为小嘛 。

**吴涛** [43:31]
对啊 。

**Rio** [43:33]
就是还是 ， 就可能我们这种情况比较特殊啊 ，有很多这种所谓的这种 ， 呃 ， 白领 ，他可能经常需要去开会啊 ， 办公啊之类的时候 ，他就需要 ， 呃 ， 拿一台电脑 ， 然后 iPad 又不行嘛 ， 这个时候那种轻薄的笔记本就有的 ， 就是一个必须的选项了 。

**吴涛** [43:52]
没错 。

### 并发并行

**Rio** [43:53]
呃 ， 今天的主题是什么 ？

**吴涛** [43:55]
今天的主题是并发 ， 嗯 ， 和异步 。

**Rio** [44:00]
啊 ， 听起来是不是又 ， 哎 ， 等一下， 这个是不是又太干了 ？

**吴涛** [44:04]
呃 ， 并发和异步 ，其实我们可以讲的比较 。

**Rio** [44:08]
泛一点的 。

**吴涛** [44:09]
比较 ， 比较浅入浅出一点 。

**Rio** [44:12]
嗯哼 。

**吴涛** [44:13]
霍金 ， 霍金不是在 《 十年电视 》 里面说 ， 嗯 ， 你 ， 你在书里面加一个公式 ， 你的读者就会少一半 。

每加 ， 每 ， 每多加一个公式 ， 你的读者就会少一半 。 所以我们想可能是我们每 。

**Rio** [44:28]
每次呢 ？

**吴涛** [44:28]
我们每 ， 每增加一个术语 ， 可能听众就会少一半 。 比如说上一期编程与数学 ， 可能已经限定了很多听 ， 很多对数学和编程不感兴趣的听众是不会听的 。

当然对数学和编程不感兴趣的听众为什么要听 《 内核恐慌 》 呢 ？

**Rio** [44:46]
没事啊 ，他们还可以听这个沐阳老师的声音嘛 。

**吴涛** [44:50]
说的也是 。

**Rio** [44:51]
哈哈哈 。 哎 ， 我们把 ， 我们应该把沐阳专门挖到 IPN 来单独做一档节目 ， 各位听众说怎么样呀 ？

然后粉丝全过去了 ， 我们这没剩几个人。

**吴涛** [45:03]
对 ， 此处应该 ， 此处应该插入那个幼儿园的所有小朋友一起说好 。

**Rio** [45:09]
哈哈哈 。 对 。 好 。 好 。

**吴涛** [45:14]
呃 ，yeah。

**Rio** [45:16]
对 。 好吧 。 所以并发和并行其实是两个概念哈 。

**吴涛** [45:21]
不不不 ， 并发和异步 。

**Rio** [45:23]
对不对 ？Concurrency 和 ， 呃 ，Concurrent 和 Parallel。

**吴涛** [45:27]
啊 ，OK， 先讲并发这一块对吧 ？ 对 。

**Rio** [45:30]
对对对 。

**吴涛** [45:30]
并发和并行 。

**Rio** [45:32]
这个 ， 这个术语其实有 ，有点很纠结的 ， 就我觉得没有一个很清晰的 ， 就起码中文没有一个很 ， 很清晰的概念吧 。

就 Concurrent， 英文里面是两个完全 ， 完全不一样的词嘛 ， 对吧 ？ 但是在中文里面你说并发和并行有什么太大区别吗 ？

好像也没有 。

**吴涛** [45:48]
但我其实我觉得就是怎么说 ，有人软件工程里面有很多很多词汇都是这样的 。 而且你说 Concurrency 和 Parallel 在英文里面的区别是每一个程序员都了解的吗 ？

可能也不是 。

**Rio** [46:01]
甚至连那个词典的定义都是很 ， 非常接近 ， 你说都没有一个很严格的区分到底哪个是哪个 。

**吴涛** [46:08]
对 。 但是我觉得可能在软件界有很多很多这样的问题 ， 比如说 Argument 和 Parameter 的差别 ， 可能有很多时候也会混用 。

嗯 。

**Rio** [46:20]
就看语境嘛 ， 就是大部分时候是不分的 ， 我觉得 。

**吴涛** [46:23]
对 。 但具体到这一期的话题上来说 ， 我觉得可能正确的区分 Concurrency 和 Parallel 也是 ， 呃 ， 就接下来的讨论比较重要的事情 。

甚至可以说 ， 如果我们这一期节目可以让 ， 呃 ， 可以帮助听过的人确切的了解了 Concurrency 和 Parallel 之间的差别 ， 那可能也已经是很有 ， 很有 ， 很有好处 。

**Rio** [46:49]
成功了 。

**吴涛** [46:49]
对 ， 很有成功的一件事 ， 很成功的一件事 。

**Rio** [46:52]
所以我们先把这个范围缩 ， 缩得很窄哈 。 就说我们在这里讲的并发和并行 ， 当然对应的两个词就是 Concurrent 和 Parallel 这两个词的时候 ，是讲在 ， 啊 ， 叫什么 ， 啊 ， 多 ， 多线程 ， 或者说在 ， 这个程序语言的这个构建的时候的一个 ， 一个 ， 一个场景 。

那至于说这个场景以外你要怎么去用这两个词 ， 那就随你便吧 。

**吴涛** [47:16]
对 。

**Rio** [47:16]
嗯哼 。

**吴涛** [47:17]
嗯 ， 所以什么是 Concurrency， 什么是并发 ？

**Rio** [47:23]
Concurrency 我 ， 我是这么理解的啊 ， 就说它是一种思维方式 ， 就说它你是怎么去在 ，在逻辑上去构建一个东西 ，是它 ， 它两个之间是可以没有一个先后顺序的依赖关系的 。

我这么解释可不是合理或者清晰 ，但我是这么理解的 。

**吴涛** [47:42]
OK。 那什么是 Parallel 呢 ？ 什么是并行呢 ？

**Rio** [47:46]
并行的话就是说这个是 ， 我 ， 我就是相对于刚才那一讲是在逻辑层面的话 ， 那个 Concurrency 在逻辑层面的一个概念的话 ， 并行可能就是在一个 ， 呃 ， 物理层面的一个概念了 。

就是说 ， 呃 ，在逻辑上并发的东西在物理上它并不一定是在并行执行 ， 它也可以是先做一个后做一个 ， 只是说它这个先后是没有太大关系的 ， 就谁先谁后都一样 。

但是并 ， 就是在实现层面的并行的话 ， 就是说它两个是在物理事件中同时发生的 。

**吴涛** [48:17]
OK。

**Rio** [48:18]
这样解释可以吗 ？ 我 ， 我觉得 。

**吴涛** [48:20]
我觉得应该是可以的 。 就是怎么说呢 ， 就是有一句 ， 就是 Rob Pike 曾经做过一个对 GoLang 的 、GoRoutine 的 ， 嗯 ，PowerPoint， 嗯 ， 叫什么 ， 幻灯片 。

**Rio** [48:35]
幻灯片 ， 对 。

**吴涛** [48:36]
就对 ， 这个幻灯片在网上可以 ， 可以得到 。 然后它的 ， 它对于并发和并行的定义是 ， 并发是同一时间应对多件事情的能力 ， 就 dealing with a lot of things。

而并行呢 ， 就是 parallel， 则是同一时间动手去做很多件事情的能力 。 就 。

**Rio** [48:57]
但这里你就要解释什么是 。

**吴涛** [48:59]
什么是 ， 什么 ， 什么是应对和什么是做 ， 对吧 ？

**Rio** [49:02]
对 。

**吴涛** [49:03]
就是你可以理 ， 我觉得可以理解为就是这两个 ， 这两个概念的抽象层级是不一样的 。 就并发 ， 或者说他们描述的问题的领域是不一样的 。

所谓并发 ，Concurrency 指的是一个比较 ， 嗯

，在问题领域的概念 。 就是你有很多问题 ， 你需要去解决这些问题 ，而这些问题的发生是同时发生的 。

你就可以说我要 ， 我所面对的问题有 Concurrency 的特征 。

**Rio** [49:38]
嗯哼 。

**吴涛** [49:38]
而 Parallel 则是在你实际去做一件事情的时候 ， 你要 ， 比如说你 ， 你要 ， 你要去解决一个并发的问题 ， 你怎么去解决它 ？

好 ， 你可以使用并行的手段去解决它 。

**Rio** [49:53]
嗯 ， 我大概理解你意思 ，但是我觉得听起来好像有点绕 。

**吴涛** [49:58]
对吧 ？ 比如说 ， 或者说举 ， 我们还是 ， 呃 ， 举例子来 ， 来 ， 来 ， 来解释好了 。 就比如说 ， 嗯 ， 我在 ， 我在做一些事情的时候需要去做另外一些事情 ， 比如说我要做饭 。

好 ， 我 ， 我 ，而且但是我的碗还没洗过也没啥 。 好 ， 那我要先刷 ， 先刷锅 ， 再洗碗 ， 然后再切菜 ， 然后再把油倒进锅里 ， 然后开始炒菜 ， 炒完菜再装盘 。

**Rio** [50:23]
嗯哼 。

**吴涛** [50:23]
呃 ， 所有这些事情可以理解为我是有些事情是可以同时做的 ， 对吧 ？ 比如说我可以 。

**Rio** [50:29]
嗯哼 。

**吴涛** [50:29]
呃 ， 先洗一部分碗 ， 然后， 呃 ， 先洗 ， 先把锅洗了 ， 然后用锅来炒菜 ， 然后在菜被煮的过程中， 假设我是做一个炖菜 ，不需要长时间的去翻它的炖菜 ， 然后我可以在炖这个菜的时候去 ， 呃 ， 洗碗 ， 对吧 ？

嗯 ， 此时我可以说做饭这件事情是一个并发的事情 。 因为 。

**Rio** [50:52]
Concurrent。

**吴涛** [50:53]
有很多 ， 对 ，有很多头绪需要我去做 。

**Rio** [50:55]
嗯哼 。

**吴涛** [50:56]
甚至我可以把买菜加进去 ， 比如说我可以 ， 我 ， 我可以去买菜 ， 先 ， 我需要先去买菜 ， 然后再去 ， 呃 ， 刷锅洗碗 ， 然后再开始炖菜 ， 然后再开始装菜 ， 然后才开始摆桌子之类的 。

**Rio** [51:06]
嗯哼 。

**吴涛** [51:07]
但是因为我只有一个人， 所以我可能没有办法用并行的手段去做它 ， 对吧 ？

**Rio** [51:12]
对 ， 没错 。

**吴涛** [51:13]
但如果我可以 。

**Rio** [51:15]
你有女朋友 。

**吴涛** [51:16]
拉着我女 ， 对 ， 首先我得有一个女朋友 。

**Rio** [51:19]
首先你得有一个 。

**吴涛** [51:20]
幸 ， 幸好 ， 幸好我已经有了一个女朋友 。 我可以拉着她说 ， 好 ， 我去买菜 ， 你把锅给我洗了 。

**Rio** [51:26]
对 。

**吴涛** [51:27]
对吧 ？ 此时我就可以说我在做并行 ，因为 ， 呃 ， 同 ， 我在同一时间同时做很多事情 ， 此时就是 parallelism。

**Rio** [51:37]
对 。

**吴涛** [51:37]
我不知道这样是不是比较 。

**Rio** [51:38]
所以 ， 所以这个从一个概括的说法来讲 ， 就是说并发 ，Concurrency 是一个组织 ， 呃 ， 事物的概念 ， 就是说你可以把事物独立出来 ， 它互相之间是没有因果关系或者是依赖关系的 。

它可以 。

**吴涛** [51:53]
对 。

**Rio** [51:53]
它可以被并发执行 。 但你实际做的时候 ， 你是 ，是不是真的同时在做几件互相可以并发的事情 ， 则不一定 。

就好像刚才你说这个做饭的例子 ， 你有很多并发的那个任务 ， 比如说洗碗是一个 ， 切菜可能是一个 ， 呃 ， 然后这个怎么洗锅可能又是一个 。

但是因为你只有一个人， 你还没有 ，并没有把这些并发的任务并行执行嘛 。

**吴涛** [52:17]
也就是说你在面对一个 Concurrency 的问题的时候 ， 你可能没有办法用 parallel 的方式去解 ， 去解决它 。

**Rio** [52:24]
嗯哼 。

**吴涛** [52:25]
而你用 parallel 的方式去解决问题 ，也有可能根本不是 Concurrency 的问题 。 但是当然后者这样的例子可能比较 ， 比较难以解出来 。

**Rio** [52:35]
哎 ， 对 ， 我刚才就在想说 ， 啊 ， 我们刚才讲了说 ， 哎 ， 呃 ， 那是不是说并行 ， 就是 parallel 的前提是并发呢 ？

你说不是 ， 那有什么反例吗 ？

**吴涛** [52:47]
呃

， 比如说吧 ， 嗯 ， 我要在五个抽屉里面 ， 我 ， 我有五个抽屉 ， 五个抽屉里面装满了围棋子 ，其中五个抽屉里面有一万个围棋子 ， 只有一个是黑的 ，其他都是白的 。

我要在这 ， 我要把那个黑的围棋子找出来 。 你说这是 ， 这是 Concurrency 的问题吗 ？ 其实不是 。

**Rio** [53:12]
啊 。

**吴涛** [53:12]
它 ， 这件事情本身没有任何 Concurrency 在里面 ，不是吗 ？ 我只需要找到那个黑 ， 找到黑围棋子是我唯一的目的 。

**Rio** [53:20]
嗯 ，但我觉得这个可能有 ， 看你的这个什么定 ， 叫什么 ， 你的 task 的划定是什么样子的嘛 。 如果你划定 task 是 ， 啊 ， 我有五个 task， 就分别在每一个抽屉里面找那个一个黑色的围棋子 ， 对吧 ？

**吴涛** [53:35]
嗯 。

**Rio** [53:36]
这个时候它又是一个并发的概念了 。 所以我觉得 ， 呃 ， 可能大致上可以这么认为吧 ， 就是说并发是并行的先决条件 ，但并行并不是并发的必然结果 。

**吴涛** [53:50]
可以这么说 。 好吧 ， 就或者说如果你可以把问题转化为一个能够并发的问题 ， 那你基本上就可以用并行的方式去解决它 。

**Rio** [53:59]
嗯哼 。

**吴涛** [54:01]
如果这个 。

**Rio** [54:01]
有很多的那个 ， 那个 resource， 就资源去 。

**吴涛** [54:04]
资源 。

**Rio** [54:04]
去并发去做嘛 。 刚才在你那个做饭那个例子里面 ， 这个资源就是说你得有两个人， 或者是三个人， 或者四个人。

但是在电脑的 ， 就是处理器这个 ， 你得有多个处理器 ， 就多核 ， 或者是多个 CPU 的 。

**吴涛** [54:19]
或者说更抽象一点就是多个逻辑单元 ， 你可能 。

**Rio** [54:23]
对 。

**吴涛** [54:24]
可以去 ， 对 。

**Rio** [54:25]
嗯哼 。

**吴涛** [54:26]
比如说 ， 对 ， 早期的计算机可能的确是不具备并发的能力 。

**Rio** [54:31]
都是单核处理器嘛 。

**吴涛** [54:33]
对 ， 甚至不是 ， 甚至是先不说单核处理器这个 ， 这件事情 ， 就是你在单核处理器上可以用 ， 可以在 ， 嗯 ， 操作系统层面去 ， 去模拟 ， 呃 ，parallelism。

但是在真正的早期的计算机里面 ， 就连 ， 连 ， 连并 ， 连这种操作系统层面的并行都是不存在的 。 就 。

**Rio** [54:55]
呃 ， 并发 ， 并发 。

**吴涛** [54:57]
呃 ， 操作系统层面的并行是不存在的 。 我觉得 ， 我想说的就是 ， 比如说那个时候并发肯定是 ， 呃 ， 存在的 。

比如说你一方面要读软盘 ， 另一方面要刷新屏幕上的字符 。

**Rio** [55:11]
这个时候你已经有那个了吗 ？ 有那个叫什么 ，有多任务了吗 ？

**吴涛** [55:16]
没有多任务 。 我的意思就是在很早很早的时代 ， 没有多任务的时代 ， 当你在读软盘的时候 ， 你的屏幕就是卡死的 。

**Rio** [55:25]
啊 。

**吴涛** [55:25]
就那个时候的计算机是没有办法用并 ， 用任何 ， 用任何不管是真实的也还是虚假的并行手段去解决这些并发的问题的 。

**Rio** [55:34]
嗯哼 。

**吴涛** [55:35]
对 。

**Rio** [55:35]
然后后来我们就有了这种就所谓的这个多任务机制 ， 就是在哪怕是在单一执行 ， 单一逻辑核的处理这个计算机上， 我们也可以就假装我们是在同时执行很多事情啊 。

比如说 ， 我看最早实现那个什么 ， 就民用的话 ， 应该是 Windows 3.2 还是 9.3.2 吧 。

**吴涛** [55:56]
你要是说最早的话呢 ，Windows，在 Unix 下面很早 。

**Rio** [56:00]
就是 ， 就是大 ， 大规模使用的情况下， 就是普通人用的 ， 应该是 9.5 吧 ， 我觉得 。

**吴涛** [56:06]
呃 ，9.5。

**Rio** [56:08]
3.2。

**吴涛** [56:09]
9.5 不是强制是多任务 ， 所以 3.2，3.2 已经有多任务了呀 。

**Rio** [56:13]
3.2 已经有多任务了 ， 意思那个时候就已经有多任务了 。 就是可以在你在实现你在前 ， 你在放一首歌的时候 ， 同时打开一个图片 ， 比如说可以做这么一件事情 。

你 DOS 时代是不能这样的嘛 。

**吴涛** [56:27]
对 ，但是如果 ， 等等 ，Windows 3.2 是 ， 可能这个术语需要解释一下， 就是 ， 啊 ， 我们说的 3.2 其实指 Windows 3.0。 因为 ， 呃 ，Windows 3.2 其实是只有中国地区才有 ，Windows 3.2 是 Windows 3.0。

**Rio** [56:40]
是这样吗 ？

**吴涛** [56:41]
不对 ，Windows 3.2 其实就是一个 Windows 3.1 的简体中文版 。

**Rio** [56:44]
啊 ， 这样 ， 我不知道 。

**吴涛** [56:46]
对 ， 所以 ， 所以我们经常说 Windows 3.2，但其实这个概念仅限于中文圈里面 。

**Rio** [56:52]
Windows 3 吧 ， 我们都有 ， 都称 ， 哈哈 。

**吴涛** [56:54]
对 ，Windows 3 是一个比较好的特名 ， 嗯 ， 嗯 ， 术语 ， 对 。

**Rio** [56:59]
对 。 然后后来就有了这个多任务 ， 就可以实现刚才那个功能嘛 。 但是那个处理器还是一次只做一件事 ， 就是它 ， 它放一会儿这个歌 ， 还有把那个处理器的核心切到去画一会儿图 ， 然后再 。

**吴涛** [57:10]
对 。

**Rio** [57:10]
再切回来放一会儿歌 ， 然后再切回来画一会儿图 。 它只要切得够快 ， 给人的错觉是说它同时在做两件事 ， 就是它在并行地执行两件并发的任务 ，但其实它只是一个单 ， 它并不是并行的 ， 它只是一个 。

**吴涛** [57:26]
对 。

**Rio** [57:26]
不太 ，不太替换的一个东西 。

**吴涛** [57:28]
它就像闪电侠一样 ， 可以自己跟自己打乒乓球 。

**Rio** [57:31]
哎 ， 这个是 。

**吴涛** [57:32]
切换得非常快 ， 对 。

**Rio** [57:34]
对 ， 这个是很好的比喻 。 啊 ， 然后真正到了要有 parallel， 就是有并发的概念 ， 还是有这个 ， 就当时有单核处理器有多线程的时候嘛 ， 就 hypersending 的时候 ， 就是一个处理器核心 ， 它模拟成两个逻辑核在用 。

好像包括到我们现在的真正的多个物理核的情况下， 甚至在一些工作站或者是服务器上， 所谓的这种多 CPU， 就是它不 ， 不只有一个 CPU 的芯片 ， 它有可能两个或者四个这样 。

**吴涛** [58:01]
对 。 这样只有到这个时候才 ， 我们才说真正的 parallelism。

**Rio** [58:06]
并行 。

**吴涛** [58:06]
对 ， 已经实现了 。

**Rio** [58:08]
对 。 不过其实并行在 ， 呃 ，在我们讲 CPU 的时候 ，是可能比较晚近才出现 ，但是它在讲那个 GPU， 就图形处理器的时候 ， 它其实一直存在的啊 。

因为我们知道 。

**吴涛** [58:22]
没错 。

**Rio** [58:23]
这个 GPU 的 ， 它是一个大规模并行化的这种一种结构 。

**吴涛** [58:28]
就是因为图像处理这件事情 ， 它与生俱来就存在着这么一个 ， 呃 ， 可以被并行执行的问题 。 就是你需要大规模地改变一张图上的每一个点 ， 那这就 ， 这就有点像你需要 ， 呃 ， 同时给两万个抽屉里 ，在两万个抽屉里面找有没有黑白黑子这样 。

所以这件事情是可以天生地被 ， 呃 ， 批量地以流水线的方式并行处理的 。 所以 。

**Rio** [59:00]
对 。

**吴涛** [59:01]
也就是因为这个 ， 这种问题的特别性 ， 所以才会有 GPU 这种东西出现 。

**Rio** [59:06]
嗯哼 。 而且就 GPU 如果你能 ， 你的问题可以被简化为 ， 啊 ， 或者不叫复杂化 ， 为这个 GPU 的那种实核模型的话 ， 你能获得的这个所谓的吞吐能力 ， 就是 throughput，是非常非常惊人的 。

**吴涛** [59:20]
没错 。 而反过来讲 ， 这也就是为什么很多跟 GPU， 跟图 ， 跟图像处理其实没有任何联系的事情可以交由 GPU 来做 ， 比如说 ， 呃 ，Bitcoin mining， 用 GPU 来做 。

就是因为它其实也是一个可以天生地被很好地并行处理的 ， 呃 ， 任务 。

**Rio** [59:41]
嗯哼 。 对于这一类问题 ， 我们一般有一个就所谓的一个名称 ， 专有名称是说这种叫做 embarrassingly paralyzing task， 对不对 ？

**吴涛** [59:51]
哈哈哈 。

**Rio** [59:52]
就非常尴尬的可以被并行化执行的问题 。

**吴涛** [59:55]
没错 。 就是好像 ， 嗯 ， 罚你 ， 小学的时候罚你把某一句话抄几百遍 ， 就大家会用五支笔 ， 啊 ， 五支笔可能非常惊人的 ， 非常了不起的小伙伴才能做到 。

**Rio** [1:00:11]
固定在一起 。

**吴涛** [1:00:12]
一般人用三支笔同时抄课文是可以做到的 。 把一个字写 2000 遍 ， 这是就是 ， 这就是一个非常 embarrassingly， 呵 ， 呃 ，parallelism task。

**Rio** [1:00:23]
没错 。

**吴涛** [1:00:24]
对 。其实这是一个很好的例子 ， 就是把 ， 把某一字抄几千遍 ， 这其实是一个 ，其实就是一个 ， 嗯 ，并不是非常 concurrency，但是可以被 parallel 执行的任务 。

**Rio** [1:00:37]
嗯哼 。

**吴涛** [1:00:38]
啊 ， 所以有一件事情是可以确定的 ， 就是现代的编程世界是离开了并发模型基本上是 ， 或者说并行处理能力是 ，是没有办法 ， 没有办法继续下去的 ， 可以这么说 。

就是比较传统的所谓 sequential programming model 是在现代的编程领域所要处理的问题面前是毫无黄金日历的 。 所以我们无论如何是需要 parallelism 的 。

那问题就来了 ， 就是 parallelism 其实是一个 ， 怎么说呢 ， 描述起来比较简单的概念 ， 或者说当你理解 。

**Rio** [1:01:14]
做起来很复杂 。

**吴涛** [1:01:15]
但 ， 但做起来人们 ， 不同的人有不同的意见的这么一个 ， 一件事情 。

**Rio** [1:01:20]
嗯哼 。

**吴涛** [1:01:21]
就最最简单的一个 ， 一种 ， 一种并发模型 ， 或者说并行模型 。 我觉得接下来的节目我们还是混用并发和并行这个词吧 ，不然实在是太累了 。

**Rio** [1:01:32]
嗯哼哼哼 。 你说呢 ？ 就是在不区分这个 ，不严格区分并发并行的场合的情况下， 这两者有时候又是在混用的 。

**吴涛** [1:01:42]
对 ， 没错 。 呃 ， 对 。 所以接下来的 ， 嗯 ， 就接下来当我说到并发模型的时候 ， 我其实我的意思有可能是并行模型 。

嗯 ，但我说并行模型的时候 ， 一般肯定是在讲并行模型 。

**Rio** [1:01:57]
嗯哼 。

**吴涛** [1:01:57]
嗯 ， 对 。 所以 ， 呃 ， 最基本的一种并行模型是什么呢 ？ 我觉得是 thread。

**Rio** [1:02:04]
线程 。

**吴涛** [1:02:05]
就是线程 ， 或者说 ， 或者说应该说最基本的一种并行模型应该是多进程 。

**Rio** [1:02:13]
嗯 ，multiprocess。

**吴涛** [1:02:14]
如果真的要 ， 呃 ， 追根溯源的话 ， 那应该可能还是多进程先于多线程出现 ， 对吧 ？

**Rio** [1:02:23]
没错 。 没错 。 因为起码在 ， 我记得 Linus 那种就是非常晚近才出现多线程嘛 ， 最开始都一直都是多进程的模型 。

**吴涛** [1:02:31]
对 ，因为在 Linux 上面开一个进程的方法 ， 开一个进程要比开一个线程简单很多 。

**Rio** [1:02:38]
对 ，而且开销也不是特别大 ， 就是它的多一个进程的开销是相对小的 。

**吴涛** [1:02:44]
对 。 至于技术细节我们就不解释了 ，但是 ， 呃

，其最根本的想法就是在一个编程语言里面 ， 如果我们要利用多进程或者是多线程的话 ， 好 ， 那我就显式地写出来 ， 这里请开一个新的进程 ， 或者利用 fork 或者怎么样 ， 然后或者说在这里请开一个新的 ， 呃 ， 线程 。

**Rio** [1:03:07]
嗯哼 。

**吴涛** [1:03:08]
用 thread。 呃 ， 然后这就是非常简单直接 ， 至少对于硬件来说非常简单直接的一种并行开发的模型 。

嗯 ，但是这种并行开发的模型有一个问题 ， 就是对于程序员来说比较挑战 ，因为 ， 呃 ， 受限于我们只有一个大脑的限制 ， 或者说我们的思维天生就是一个 。

**Rio** [1:03:35]
线性的思维啊 。

**吴涛** [1:03:37]
一个单线程的 ， 一个单进程的思维 。 所以在理解多进程的时候 ， 呃 ， 会有一个 ， 会有一个 ， 会有个坎儿 。

我不知道你怎么样 ，但是当我写出人生第一个多进程的程序的时候 ， 我是 ， 我是愣了很久的 。 就是我需要 ， 我需要去 ， 去拥有那种精神分裂的能力 ， 就是在这个地方我需要判断说 ， 啊 ， 我的 PID 是 0， 那我是一个新的进程 。

呃 ， 那接下来我所要做的这件事情 ， 然后另外一件事情则要在我的副进程里面进行 。 然后这个时候我就会有一种 ， 会有一种 ， 会有一种 ， 呃 。

**Rio** [1:04:20]
兴奋的感觉 。

**吴涛** [1:04:21]
对 ， 会有一种非常兴奋的感觉 ， 就会觉得说 ， 好吧 ， 那

计算机解释这一切的时候可能会比较 ， 比较方便 。 但是我 ， 我就会不停地去想说 ， 哦 ， 那我现在是在副进程里还是在子进程里呢 ？

那我做完这件事情 ， 我 ， 我要 ， 我要回到副进程里面 ， 那副进程里面要做收尾工作 。 可是万一子进程没有及时地完成这些事情 ， 副进程要等它吗 ？

就是在我相 ， 我记得在 ， 呃 ， 学操作系统还是什么的时候 ，有很大一个篇幅都是在讲多进程或者多线程的实现原理的 。

就比如说什么很多很经典的 ， 呃 ， 数学问题 ， 数学模型也是在这个领域被提出来的 ， 比如说什么 ， 我忘了 ， 哲学家吃饭问题 ， 就是什么一个哲学家左边是刀右边是叉 。

**Rio** [1:05:12]
饿死了 。

**吴涛** [1:05:12]
对 。

**Rio** [1:05:12]
Dining philosophers problem。

**吴涛** [1:05:14]
没错 。 呃 ， 等等 ，而且我觉得我印象里面没 ， 没记错的话 ， 这本书的英文版里面哲学家是左手刀 ， 左手刀右手叉 ， 然后到中文版里面变成了哲学家左右各有一只筷子 。

你只有 ， 就连这个地方要本地化一下， 你必须 ， 你必须拿到两只筷子才可以进餐 。

**Rio** [1:05:35]
嗯哼 。

**吴涛** [1:05:36]
对 。 我记得那个时候特别可笑 ， 呃 ， 当时课堂上有个同学讲了一个笑话 ， 就说他们为什么不都换成长勺子 ， 然后互相喂饭吃呢 ？

这就跟 ， 这就跟另外一个 ， 呃 ，也是哲学上的一个 ， 一个 ， 一个笑话联系来了 。 就是说哲学上说 ， 呃 ，有一个 ，有一堆人围坐在一口锅前面要吃饭 ，但是每个人的勺子都特别长 ， 呃 ， 没有办法把它转过来喂自己吃饭 。

所以每个人必须去喂对方吃饭 ， 所有人才不会饿死 。 然后这个故事被它在这边转移到这个哲学家饿死问题里边 ， 我觉得当时特别有喜感 。

**Rio** [1:06:17]
哈哈哈 。 意思 。 嗯 ， 刚才讲你说这个并发 ， 呃 ， 这个并行 ， 并行编程 ，parallel programming 的一个核心的问题就是可能对程序员的要求就 ， 就 ， 就不是 ， 就是数量级的提高吧 。

因为确实如你所说 ， 这个人的思维很多呢 ， 它是一个单线的一个过程 ， 它没办法去同时考虑 ， 啊 ， 你大脑不是一个多 ， 多核的东西嘛 。

**吴涛** [1:06:43]
没错 。

**Rio** [1:06:44]
那么就其实就 ， 就可能在传统的线性编程的情况下， 你 ， 你 ， 你 ， 你的这个思维逻辑跟着这个程序 ， 程序代码走一遍 ， 你也知道计算机也是这么执行的 ，并且不会有任何人干扰你中间这个执行的步骤 ， 当然可能中断啊 ， 那些什么除外哈 。

呃 。

**吴涛** [1:07:00]
没错 。

**Rio** [1:07:01]
但是在一个并行的条件下， 这个事情就变得非常诡异了 。 就是如果你不考虑什么锁的那些机制啊 ， 什么同步机制的话 ， 它是有无限多种可能 ，有两个 ， 就是两个或者多个这种线程也好 ， 进程也好 ， 它可以 ， 我们叫做 interleaving 嘛 ， 就是互相交织在一起 。

**吴涛** [1:07:20]
互相交织 ， 对 ， 没错 。

**Rio** [1:07:21]
对 。 这个时候你就很难去看 ， 看明白说 ， 啊 ， 或者说你要你的脑袋中要装的那个 ， 那个 state space， 就是它你到这一步的时候 ，其他人可能会怎么样 ， 这种东西它就是一个指数增长的东西 。

所以这个时候对人的思维挑战确实是一个极其困难的一件过程 ， 一个 ， 一个过程 。 而且 ， 啊 ， 就为了解决这个问题呢 ， 就是我们也有很多这种方案嘛 ， 比如说 ， 啊 ， 最可能我们听得最多的一条就是说 ， 叫做 share the mutable state is bad is evil， 对吧 ？

就是如果你是 ， 你是并行 ， 并行编程的东西 ， 然后你还要多个线程也好 ， 进程也好 ， 去共 ， 去同时访问一个可以被改写的一个 ， 一个 ， 呃 ， 内存区域或者是变量或者文件也好 ， 这个时候你就非常困难了 。

因为你 ， 你没有办法从 ， 从那个被改写的那个区域的角度来看 ， 会 ， 你会 ， 你能预测到会产生什么样的组合 ，因为这个组合是不确定性的 ， 是一个叫做 ， 啊 ，indeterministic， 就是 ， 呃 ，不 ，不确定性的一个过程 。

**吴涛** [1:08:22]
没错 。

**Rio** [1:08:23]
啊 ， 所以这个很多时候我们的一个解决方案就是说 ， 那么最好就是叫做 share the nothing， 就是一切都不要共享的结构 。

这样的话有什么好处呢 ？ 这样你就可以在并行的环境下， 对于某一个线程或者是进程也好 ， 你不用考虑它和别的进程和线程的交互怎么样 ， 你只用考虑它自己本身是一个线性的 ， 线性的程序走下去就好了 。

这个时候就等加 ， 等于说是把一个并行的问题变成了一个线性的 ， 呃 ， 串行的问题来解决了嘛 。

但实际上这种 ， 这种情况是不太可行的 。 就可能有一些比较极端的例子是所谓这种 share nothing 结构的东西 ， 比如说我们很多的这个网页服务器 ， 它可能就是 ， 比如说 Apache 就是一个很典型的例子啊 ， 它每一个请求来 ， 它可能都是开一个新的进程 ， 或者开一个新的线程来 ， 来响应这个请求 ， 然后响应完毕 ， 这个进程或者线程也就被杀掉了 ， 像这个传

统的模型哈 。 然后在 ，在这个响应这个请求的线程或者是进程执行的过程中， 它你是不用考虑别的线程或者进程怎么样 ，因为你没有共享任何东西嘛 。

但是在实际应用中， 很多时候你确实是要共享东西的 ， 比如说我们现在很多做什么 WebApp， 对吧 ？ 你是要访问一个共享的数据库的 ， 那你可能要访问一个 ， 呃 ， 同一个 ， 同一个共享的数据库 ， 然后你可能要改写东西 ， 这个时候你又变成本来是一个 share nothing 东西 ， 又变成有一个 ，有一个 shared mutable state。

这样的话你的这个整个模型就又变得很复杂 ，而且难于测试起来了 。

**吴涛** [1:09:52]
呃 ， 线程加上锁这种结构就好像一个到处漏水的桶 ， 你总会觉得我堵住这个孔就没问题了 。 但是因为你堵住了这个孔 ， 所以水压变高了 ， 它会从另外一个地方漏出来 。

所以有时候用 ， 用线程和锁编程的时候 ， 你会觉得自己不仅思考的 ， 对 ， 思考的层级非常低 ， 就是你会被迫自己 ， 你迫使 ， 强迫自己像 ， 像 ， 像一个线程管理器那样去思考 。

而且与此同时你会发现解决了一个问题 ， 另外一个问题又冒出来了 。

**Rio** [1:10:26]
对 。

**吴涛** [1:10:27]
对 。

**Rio** [1:10:28]
顾此失彼嘛 。

**吴涛** [1:10:29]
没错 ， 顾此失彼 。 这就是为什么 ， 呃 ， 虽然线程或者说多线程或者多进程加上锁这种机制在几乎所有像样的 ， 像样一点的程序里面都有支持 ，但是用好它们却是非常 ， 非常难 ，而且我觉得这种难是没有必要的一种难的事情 。

**Rio** [1:10:50]
嗯 ， 就是这是一个可能不是一个太好的抽象 ， 就得出的这么一个 。

**吴涛** [1:10:55]
对 ， 它的抽象层级可能实在是太低了 ， 就有点像 。

**Rio** [1:10:58]
或者说它抽象的那个角度是错的 。 就是 。

**吴涛** [1:11:02]
呃 ， 或者说它 ， 我怎么说呢 ， 我不 ， 我觉得它抽象的角度没有错不错之分 ，因为在操作系统层面上， 并行就是这么 ， 就 ， 就是这么被实现的 。

它 ， 它与其说它的抽 ， 它的 ， 它的抽象角度是错的 ，不如说它 ， 它所抽象的东西实在是太少了 。

就是基本上你要从非常底层的 。

**Rio** [1:11:23]
不够有用的抽象 ， 对不对 ？

**吴涛** [1:11:25]
没错 。 这就是为什么接下来我们会提到几种其他的 ， 嗯 ， 并行模型 ， 就是它们试图从 ， 它们试图从不同的角度去解决这个问题 。

但是 ， 呃 ， 如果我没说错的话 ， 很多并行模型的基本实现原理还是通过线程和锁 。

**Rio** [1:11:49]
没错 ， 就底层它是这么实现的 ，但是只是它 ， 它暴露给这个开发者或者程序员的这么一个 ， 呃 ， 一个接口或者是一个表象 ， 它并 ， 你看不到那些东西了 。

**吴涛** [1:12:00]
对 ， 这其实是回到我们前很 ， 很多 ， 至少很长时间以前讲的封装的那么一个 ， 那么一个 ， 呃 ， 问题领域 。

就是我们接下来要介绍的几种并发模型其实是对于多线程加锁的这样一种封装 。

**Rio** [1:12:20]
嗯哼 。

**吴涛** [1:12:20]
但是这种封装 ， 当你熟悉了它之后， 你会发现它在很大程度上增加了你思考的 ， 嗯 ， 方便程度 ， 或者说让你变得更像一个人了 ，而不像一个机器 。

**Rio** [1:12:35]
不用再在头脑中模拟 ， 呃 ， 费劲地用一个单核处理器的大脑去模拟一个多核处理器的 CPU 了 。

**吴涛** [1:12:43]
对 ， 没错 。 呃 ， 那你觉得 ， 嗯 ， 除了多线程的模型之外， 哪一种并发模型是最 ， 最简单 ， 或者说最直接能够让人比较方便接受的 ？

**Rio** [1:13:01]
嗯 ， 那最好就是让 ，不要让我去想 ， 去让我思考有这些底层 ， 这些就是 ， 就最理想的模型是不要让我思考有这么一些东西存在的东西嘛 。

那可能用从语言层面上来解决这个问题的话 ， 如果你能实现 ， 好像传统意义上的什么 FP 嘛 ， 就是函数式编程的话 ， 就可能就 ， 就根本不用考虑这个问题了 。

因为函数式编程 ， 每一个函数在 ， 就是在纯粹的一个函数式编程里面 ， 所有的函数都是所谓的确定性结果的嘛 。

这样的话 ， 就不管你怎么去执行它 ， 你总是得到一个确定性的解的 。 那我不管你是顺序执行 、 并发执行还是怎么样 ， 你一个什么一阵一组合我都不用管 ， 我只用考虑这个函数是这么写的 ， 得 ， 我输入这个数得到这个结果 ， 那就完了 ， 就根本不存在并发 、 并行这些概念在里面 。

**吴涛** [1:13:51]
没错 ， 我觉得可能 Functional programming 所 ， 所给我们最大的 ， 嗯 ， 益处就在于之前我们讨论的 ， 嗯 ， 线程加锁所要解决的最基本的问题 ， 就是有一个 changeable state 被 ， 呃 ，Functional programming 彻底抹去了 。

就是如果一切问题的输入乃至其中间状态全都是确定的话 ， 那别人根本不可能改它 ，在我看来我也就不需要锁了 ，不是吗 ？

**Rio** [1:14:27]
对啊 。

**吴涛** [1:14:27]
所以这就是为什么 Functional programming 为我们提供了 ， 提供了这样一种从完全从不同角度去实现并 ， 去实现并行的机制 ， 呃 ， 会让我们思考起来更方便的原因 。

**Rio** [1:14:40]
对 ， 就是说到一个最极端的例子 ， 就是如果从 ， 从先不考虑这个实现的这个经济性来讲啊 ， 就是说起码从逻辑上来讲 ， 如果你整个语言是一个纯粹的 functional 的一个 ， 一个 ， 就是纯粹是一个函数式的过程的话 ， 所每一步执行都是可以被并发执行的 。

就理论上说你每一步都可以分配到任意多个处理器上去同时执行 ， 然后得到一个解 ， 然后再进行下一步的这个 ， 这个分 ， 叫什么 reduction， 然后得到一个最终的解出来嘛 。

**吴涛** [1:15:08]
对 。 嗯 ， 对 ， 然后这样一种模型它所带来的便利是非常显著的 。 但是从另外一个角度讲 ， 嗯 ，Functional programming 写起来也是比较具有挑战性的 ，因为 ， 嗯 ， 你只是 ， 或你不只是 ，但是当你没有 global changeable state 的时候 ， 你就会需要用另外的方法去解决它 。

而 Functional programming 可能会要求你比较 ， 嗯 ， 痛苦地去转化你的思维模 ， 思维模型 。 那有没有一个比较好的例子可以说明为什么 Functional programming 可以比较 ， 嗯 ，有效地实现并发模型呢 ？

**Rio** [1:15:59]
嗯 ， 我觉得可能最简单就是一个计算机的例子就能够可能比较容易懂吧 。 就是我们计算一个 ， 呃 ， 常用的四则运算的时候 ， 我们比如说 ， 我举个最简单的例子 ，3×4， 呃 ，+5×6， 这几个 ， 这个公式我们如果人做会怎么样 ？

那我们现在算 3×4， 呃 ，12， 所以写在一边 ， 然后再算 5×6 等于多少 ？30 写在一边 ， 然后再两个求和加起来 32， 对吧 ？

**吴涛** [1:16:27]
没错 。

**Rio** [1:16:28]
但是如果是给机器来做的话 ，因为你这 ， 你 ， 你整个四则运算中间的每一步都是确定性结果嘛 ，因为确定性输入的确定性结果 ， 这样的话它可以同时计算 3×4 和 5×6， 或者说是它是甚至先计算 5×6 再计算 3×4， 然后再把再去全部之和 。

就是在这个过程中你可以看到 ，不管你的这个计算结果并不会因为你计算的顺序有任何改变而导致你的这个结果有任何变化 。

这个时候的话 ， 那机器就可以做很多很多这样的 ， 呃 ， 优化 ， 就可以把那些 ， 呃 ， 能够同时并行执行的东西都并行起来 。

**吴涛** [1:17:07]
对 ， 假设你的这个算式 ， 呃 ， 没有像 3×4+5×6 这么 trivial，而是一个比如说 200 位的数字乘以 200 位的数字 ， 然后， 呃 ， 这样的 ， 然后要给比如说五六百个这样的 ， 呃 ， 结果求和 ， 那这样的多任务 ， 呃 ， 这样并发的模型就会很好用 ， 很好地用 Functional programming 的并行模型来解决 。

嗯 ， 甚至我觉得其实也是一个很好的 MapReduce 的 。

**Rio** [1:17:38]
没错 。

**吴涛** [1:17:39]
嗯 ， 的解决的 ， 怎么说 ， 一个 ， 嗯 ， 例子 。 如果你要向一个门外人， 门外汉解释什么叫 MapReduce， 当然门外还有外人要对 MapReduce 产生兴趣 ， 这是另外一个问题 。

但如果你要向一个人解释什么是 MapReduce， 你就会说让你算 ， 让计算机去算 3×4+5×6， 呃 ，Map，Map 这一步就是给一颗 ， 给让一个计算器算 3×4， 然后另 ， 让另外一个算 5×6，而 Reduce 则是把 3×4 的结果和 5×6 的结果加在一起 。

**Rio** [1:18:10]
没错 。

**吴涛** [1:18:11]
没错 。

**Rio** [1:18:12]
啊 ，但是这个就是函数式编程这种什么说有这么好的这么特性 ，但是它问题是在什么地方呢 ？ 问题在于 ， 呃 ， 现实世界的很多问题并不能简单或者很方便地归结于一个函数式 ， 一个就叫非可变状态的一种 ， 一种场景来去解 。

比如说 ， 啊 ， 最简单的一个输 ， 输出的时候你就会牵涉到跟外部世界的状态的沟通了 。 这个时候根据你的这个输入和的这个值不一样 ， 你呢 ， 可能某一些计算结果就如果它是依赖于外部输入的话 ， 它就并不是一个你可以在单看这个程序本身可以预见的一个解 ， 预见的一个解了嘛 。

**吴涛** [1:18:54]
对 ， 比如说我们最常打的 ， 最常练习的一种 ， 嗯 ， 编程 ， 呃 ， 题目就是问操作者的名字 ， 然后打出 Hello 操作者的名字 ， 这个就是没有办法用 Functional programming 写出来的 。

就纯粹的 Functional programming 是没有办法处理这种问题的 ，因为你总有一步要问操作者的名字到底是什么 。 如果 ， 如 ， 如果他的名字 ， 就或者说在你获得他的名字之前 ， 你是没有办法把输出他的名字这一步和问他的名字这一步 ， 呃 ， 并行执行 。

**Rio** [1:19:29]
对 ， 还有一个 ， 还有一个 Functional， 呃 ，program 就不能很方便地 ， 就不能归结于纯粹的 Functional programming 的一个概念 ， 就是随机数 ， 对吧 ？

比如说你要有 ， 你要 ， 你要一个函数的结果是你每次执行它的时候得到都是不确定的结果 ， 这个时候它就并不是一个 ， 它甚至都不是一个函数 ，因为我们讲函数它应该是一个确定 ， 确定的结果嘛 。

就给定输入的时候你应该给有确定的结果 ，但如果你的这个结果是摇骰子 ， 那它本身就不是一个函数 ， 甚至严格意义上它并不是一个函数了 ， 数学的 ， 数学概念的函数 。

**吴涛** [1:20:02]
没错 ，其实这也就是 ， 嗯 ， 数学世界和统计学世界的一个根本分野 。 统计学世界所研究的世界是包含随机数发生源的 ，而数学世界 ， 数学世界所处理的问题是没有这种东西存在的 。

**Rio** [1:20:18]
OK。

**吴涛** [1:20:18]
Yeah。

**Rio** [1:20:19]
嗯 。

**吴涛** [1:20:20]
嗯 ， 对 ， 那说完了 Functional programming 解决并发模型的 ， 或者说 Functional programming 作为并发模型之后， 嗯 ， 我们可以说说其他的比较不那么 radical 的 ，不那么 。

**Rio** [1:20:37]
疯狂的主题 。

**吴涛** [1:20:39]
对 ，不那么彻底革新人们的世界观的 ， 呃 ， 并发模型 。

**Rio** [1:20:45]
OK。

### 并发模型

**吴涛** [1:20:45]
那 ， 对 ， 所以 ， 呃 ， 我们刚才提到 Rob Pike 的那一篇 ， 那一个展示 ， 就是他向人们介绍 GoRoutine 的那个展示 ， 所以作为一个 GoLang 的传福音者呢 ，Rio 你对 ， 呃 ，GoLang 的并发模型是怎么理解的 ？

或者说你可以简单地介绍一下 GoLang 里面是怎么解释 ， 怎么解决并发问题的 ？

**Rio** [1:21:08]
OK， 就 Go 里面它采用的并发模型其实是一个非常古老而且被就是学术界研究得很透彻的一种模型嘛 。

简单来说就是叫做 CSP 嘛 ， 就是 Communicating Sequential Processes。 什么意思 ？ 就是说每一个 ， 啊 ，他们叫 process， 这里是进程 ， 当然可能包括物理上是一个超性的进程也好 ， 还是这个 ， 呃 。

**吴涛** [1:21:29]
线程 。

**Rio** [1:21:30]
超性的线程也好 ， 它这 ， 这个没有关系 ， 这种 process 是一个逻辑的概念 ， 就是它是一个线性执行的一个单元嘛 。

然后他说什么意思呢 ？ 就是说每一个 ， 就刚才跟你讲的嘛 ， 每一个 ， 呃 ， 每一个进程都是单独自己 ， 自己管自己执行的 ， 它只是在需要跟其他进程交互的时候才通过消息传递的方式来做这么一件 ， 呃 ， 事儿 ， 就等别人发消息给它 ， 或者发消息给别人， 然后就有一个叫做 synchronization point 在那个点之后， 然后它完成了这一步之后， 它又再回到自己的一个 ， 一个比较线性的 ， 呃 ，

执行 ， 呃 ， 方式去做下去 。 这个是一个比较可能简单的解释吧 。

**吴涛** [1:22:10]
那所以这个 synchronized point 跟锁的差别是什么 ？

**Rio** [1:22:15]
呃 ， 它本质上就是一个锁 ， 只是说在 ， 在逻辑的这个 ， 就在抽象的方式或者抽象的角度上， 它是 ， 它是有点不太一样的 。

它并不是说 ， 哦 ， 我们两个进程要共享一个 ， 呃 。

**吴涛** [1:22:28]
资源 。

**Rio** [1:22:29]
一个 ， 共享一个 ， 对 ， 共享一个 state 了 ， 所以我们先把它锁住 ， 然后我们想 ， 呃 ， 谁先解 ， 就是谁先到达那个锁点的时候先等一下， 等另外那个人到达那个锁点 ， 然后再把那个锁解开 ， 然后我们再把那个资源改变 ， 然后再把这个锁解开 ， 然后那个被锁住的人才可以接着进行下去嘛 。

它这样的话就 ， 就有你要去想 ， 哦 ， 什么哪个资源是需要被锁定的 ， 这就挺麻烦嘛 。 然后它这个 CSP 的话 ， 它就说那我们不要去考虑这个锁的问题了 ， 我们默认我们要互相通讯的时候就是有一个隐含的锁 ， 那个锁的 ， 的锁的内容就是我要传递的这个消息嘛 ， 对不对 ？

然后对方取得了这个消息之后， 那我这个锁就解开了 ， 那我可以继续往下走下去 。 就所以它 ， 它本质上是一个锁了 ，但是只是说它的抽象的层级是不一样的 ， 或者抽象的出发点是不一样的 。

这样的话对人们或者对这个程序员来理解起来 ， 它来说是更加现实一点的 ， 呃 ， 更加现实的一个抽象吧 。

**吴涛** [1:23:27]
没错 ，其实 ， 嗯 ， 我听过一个比喻 ， 就是传统的现成与锁有点像储物箱 ， 呃 ， 你要去买东西 ， 然后你要先把自己的 ， 你在进商场之前需要把自己的东西锁在一个储物柜里 ， 显式的锁其实就是正儿八经的锁 ， 当你把一个储物箱锁起来的时候 ， 别人就不能再用了 。

而 ， 嗯 ， 这样一种 CSP 的模型则是有一个专门的储物管理员 ， 你只需要把你的东西给他 ， 说我要把这个东西存起来 ， 然后我去别的地方 。他也许在背后有另外一个储物箱 ，但是你不会去直接 。

**Rio** [1:24:07]
你不用关心这个细节嘛 。

**吴涛** [1:24:08]
没错 ， 你不用去直接关心这个你的东西到底锁在哪个箱子里了 ，以及你是不是和别人共享了同样一个储物箱这样的这类问题 ， 你只需要告诉他说我要存东西 ， 然后我走了 ， 然后等我回来的时候我要拿东西 ， 就这么简单 。

**Rio** [1:24:22]
这个 ， 这个比喻很 ， 很好哈 ， 就你回来拿的时候你就说我要拿我之前那 ， 或者说你甚至不一定是你本人去拿 ， 比如说你的老婆帮你去 ， 去拿你的包 ，但是她有那个什么牌嘛 ， 对吧 ？

她就说哎 ， 我要拿这个几号的那个 ， 那个包 ， 然后那个 ， 那个柜台那个小姐就去帮你拿出来 ， 然后你就等 ， 你中间并不需要去关心它后面有多少个锁格 ， 对吧 ？

它后面的锁是一个拉锁呢 ， 还是一个防盗保险柜呢 ， 还是一个什么样的东西实现的 。

**吴涛** [1:24:49]
对 ， 嗯 ， 所以这样一种编程模型也是目前比较 ， 嗯 ， 比较流行的一种模型吧 ， 我觉得 。 就是在很多语言里面都支持它 ， 就 ， 呃 ，Go 有 Go， 嗯 ，Go 而且是在语言层面上直接支持它的 ，而其他很多语言也都是通过一个 library 或者是其他什么机制 ， 一个 ， 一个 ， 主要是通过 library， 好像只有两种可能吧 ， 你要么在执行 ， 你要么在语言里面直接执行它 ， 要么通过一个 。

**Rio** [1:25:17]
这里要肯定要介绍一下， 就除了刚才讲的那个 CSP 模型之外， 有一个与它形成叫做对偶关系的一个模型 ， 叫做 Actor Model， 这个 Actor 我不知道这个中文怎么翻译好 ， 叫做 ， 嗯 ， 演员模型也不对吧 ，Actor 这里不是演员模型 。

**吴涛** [1:25:35]
Actor Model。

**Rio** [1:25:36]
就是简单地讲 ， 就说你在 CSP 的时候有一种 ， 就从经典的方式是说我们两个之间实现一个所谓的这个 ， 呃 ，channel， 一个 ， 一个渠道 ， 我们通过这个渠道来发送这个消息 ， 对吧 ？

**吴涛** [1:25:49]
嗯哼 。

**Rio** [1:25:50]
就说这个渠道就是我要发消息的时候 ， 我要 ， 我是先把这个消息 ， 呃 ， 通过这个渠道传 ， 传送给你 ， 如果你那边没有接 ， 没有 ， 还没有来接收这个渠道 ， 我得我发消息这个人还得在那边等着你接收之后才可以了 ， 才可以走 。

大家有没有摸着这个意思嘛 ？

**吴涛** [1:26:08]
是 ， 嗯 ， 所以 Actor， 比如说支持 Actor 的语言像 Erlang 或者是 ， 嗯 。

**Rio** [1:26:17]
Scala 也是一个 。

**吴涛** [1:26:18]
Scala 支持那个叫什么 ，不过 Scala 是通过 Akka 支持的嘛 。Scala 没有原生的 Actor。

**Rio** [1:26:24]
它有 ， 它原生是 Akka 的 ， 它也可以通过 JVM 走 Akka，Akka 那个 ， 那个 library 来实现 Actor Model。

**吴涛** [1:26:30]
OK。

**Rio** [1:26:31]
嗯哼 。 然后刚才讲的是那个 CSP 是通过 channel 来实现的嘛 ， 就是说两个人要同时到达那个 channel 那个点 ， 然后才能够传递消息 ， 啊 ， 然后这 ， 这是一种方式 。

**吴涛** [1:26:43]
对 ，而 Actor 更像一个 ， 怎么说更像一个代理 ， 嗯 。

**Rio** [1:26:46]
Actor 是一个叫做 ， 呃 ， 呃 ， 呃 ， 邮箱的模型 ， 就是说每个人， 就每个进程都是一个所谓的一个 Actor， 然后它每 ， 它就每 Actor 就只做自己的事情 ， 然后但是每个 Actor 呢 ， 它有附 ， 它有一个给它唯一配备的一个邮箱 ， 然后别人的消息来的时候呢 ，并不直接被这个消 ， 这个 Actor 拿去 ，而是说先塞进这个邮箱里面 ， 然后等这个 Actor 处理 ， 它执行到一 ， 一 ， 一个 ， 一个条件之

后， 它说哎 ， 我需要收一个邮件 ， 然后它再去看自己的邮箱说哎 ，有没有别人给我发过来的消息 ， 我看一下处理一遍 ， 如果没有的话我再继续接着做我自己的事情 。

所以 CSP 和 Actor Model 是两个 ， 呃 ， 本质上是做的同样的一件事情 ， 只是说它们在 ， 在实现方式上是有一点所谓的对偶关系的在里面 。

**吴涛** [1:27:35]
OK。

**Rio** [1:27:35]
嗯 ， 啊 ，在 ，在现实中其实 Go 的话比较 ， 它并不是一个纯粹的 CSP 的模型 ，因为它的那个 channel 刚才讲了嘛 ， 它并不是一个完全是阻塞的 channel，因为它的 channel 是可以被 buffer 的 。

**吴涛** [1:27:50]
对 ，其实我就刚才想说 Go 的 channel 难道不也是一个邮箱吗 ？ 就它也是一个 Q 啊 。

**Rio** [1:27:56]
对 ， 所以这个就是有一个 ，有一个它的 ， 它不是一个纯粹的 CSP 的这一点 ， 就是因为说它那个 channel， 它 ， 它鼓励你使用一个叫做 blocking channel 嘛 ， 就一次只能发一条消息 ， 然后你必须要等对方取出这个消息之后， 你这些发送方才能接着执行下一步 。

**吴涛** [1:28:11]
对 ， 这就是一种比较纯粹的 CSP 的状态 。 但是如果你不用阻塞式的 channel 的话 ，其实 Go somehow 也是用到了 Actor。

**Rio** [1:28:21]
没错 ， 就是它 Go 的话其实也是有一个 ，因为它的 ， 它的 channel 有一个 ， 呃 ， 扩展 ， 就是说它那个 channel 是可以有一个 buffer 的 ， 就是一个缓冲区域的 ， 比如说我可以声明这个 channel 有一个 100 个位子的缓冲区域 ， 什么意思呢 ？

我可以往这个 channel 里面塞 99 条消息都不阻塞 ， 直到我塞第 100 条消息的时候 ， 啊 ，不对 ， 我可以往那个里面塞 100 条消息都不阻塞 ，但我往里面塞第 101 条消息的时候 ， 我得等那头那个人， 就是接收方 。

**吴涛** [1:28:51]
挪出一位 。

**Rio** [1:28:52]
挪出一条消息之后， 我才能够再往里面塞进去 ， 就是说它是有一个这么一个 buffer 这么一个概念 。 然后这个时候的话 ， 这种 channel 就比较类似于 Actor Model 里面的这个叫什么 ， 啊 ， 啊 ，mailbox 信箱的概念了 ，但是就是它没有那么 ， 就灵活度和这个 ， 呃 ， 自由程度还是不一样的 。

比如说 Actor Model 里面 ， 你如果你有信箱的概念的话 ， 你必然的推论就是每一个 Actor 它是有一个唯一的确定的那个 ， 呃 ， 识别符的一个 ID， 对吧 ？

你才知道你这个 ， 你这个消息是要发从 ， 从哪里来发给谁 ， 对吧 ？ 你得有这么 ， 这么一个过程 。

但是在 Go 里面的话 ，因为你可以每一个 pro， 每一个进程是可以建立多个 channel 的嘛 ， 所以它的这个对应关系是不太一样的 ，但本质上它们是其实同一件事情 。

**吴涛** [1:29:38]
所以我们可以说 Actor 模型天生就比较适合分布式计算的领域 ，因为分 ， 当你把你的计算模型采用分布式的方式来实现的时候 ， 那每一个分布式的 ， 呃 ， 单元都会天生的带有一个 ， 呃 ， 标识符 ， 然后在这种状况下你用 Actor 模型的时候就非常容易的把你的抽象层级 ， 呃 ， 连在一起了 。

**Rio** [1:30:05]
嗯哼 。

**吴涛** [1:30:06]
但是如果用 GoRoutine 的 channel 的话 ， 那可能应用在分布式分布计算的时候没有那么 ， 没有那么自然 。

**Rio** [1:30:15]
嗯 ，其实没有 ，其实没有关系 ， 这两个是可以完全互相 ， 就是可以 ， 呃 ，不损失任何 ， 呃 ， 抽象层级的互相转化的 。

比如说最简单一个转化的道理就是说 ， 那我每 ， 我怎么在 ， 呃 ， 用 channel 实现这个 Actor Model， 呃 ， 很简单一个道理 ， 就是说我每一个 process 我自建 ， 我在建那个 process 的时候 ， 我给它一个参数就是一个 channel， 这个 channel 我就是把它命名为一个叫做命名为邮箱 ， 然后这个 ， 这个因为 channel 是有 ID 的嘛 ， 这样的话我就可以认为具备这个 channel 读写功能的那个 ， 那个进程就是这

个 Actor 本身 。

**吴涛** [1:30:53]
对 ， 我的意思就是你在这样一种解决方案的 ， 你在实施这样一种解决方案的时候 ， 你实际上是采用了 Actor 模型 ， 你只不过是在用 channel 的方式去模拟它而已 。

而 ， 呃 ， 我们就不要去考虑这个使用 ， 使用一种语言的机制去模拟 Actor 模型和真正使用 Actor 模型之间的差别在哪 。

呃 ， 我的意思是当你使用另外一种语言 ， 当你使用 GoLang 的 feature 去模拟 Actor， 呃 ，Actor 模型的时候 ，其实也就意味着 Actor 模型是比较适合在这样一种 ， 呃 ， 问题领域里面实施并发的模型 ，不是吗 ？

**Rio** [1:31:32]
嗯 ， 我不太清楚

， 就我觉得不一定 ， 就是有些 ，有些时候是用 channel 模型是更合适的 ，有些时候是用那个 Actor 模型是更合适的 。

所以你怎么去选择它 ， 我觉得还是要看你问题的 ， 就你手上具体的问题的这个 ， 啊 ， 本身的属性来决定的 。

就不一 ，不 ，并不是说 Actor 模型就一定天然比这种 CSP 的模型要 ， 啊 ， 来的 ， 呃 ， 更直观或者是更易懂这样 。

**吴涛** [1:32:02]
好吧 ， 那大概

我想想啊 ， 我们介绍了传统的现成与锁 ， 介绍了 FP， 介绍了 CSP 和 Actor， 那基本上我们可以说已经涵盖了比较主流的这种并发模型 。

对 ， 当然 ， 嗯 ， 还有一些其他的并发模型 ， 比如说有一本书叫 ， 嗯 ， 叫什么 《Seven Parallelism in Seven Weeks》， 七 ， 七周七种并发模型 ， 就它那本书里面已经介绍了七种 ，但是我们今天只说了四种 。

但是如果我印象没错的话 ， 那它提到的其他三种其实都是 ， 怎么说 ， 要么是我们提到的这 ， 呃 ， 四种比较基本的并发模型的混合 ， 嗯 ， 或者就是在更大规模上的抽象 。

当然我不是 ，不是印象不是很深了 ，但是我推荐如果有 ， 如果对这个问题比较感兴趣的听众们可以去看一看这本书 ， 就是它是另外一本叫做 ， 呃 ，《Seven Language in Seven Weeks》 的 ， 的姐妹书 ， 另外一本书也很好 。

**Rio** [1:33:15]
嗯哼 。

**吴涛** [1:33:16]
OK。

**Rio** [1:33:18]
然后我们要就要过渡到下一个相关但并不同 ，并不等同的话题了哈 ， 就是所谓 。

### 异步IO

**吴涛** [1:33:26]
应该说是在抽象层级上并不等同 。

**Rio** [1:33:28]
对 ，但是它有点相关 。

**吴涛** [1:33:31]
没错 。

**Rio** [1:33:31]
就是所谓的这个异步和这个非阻塞式的一个程序设计 ， 程序语言的设计吧 。

**吴涛** [1:33:38]
没错 ， 就是当刚才 ， 刚才我们提到了在 ， 呃 ，Functional Programming 难以 ， 非常难以解决的一个问题就是 ， 当你要处理 IO 的时候你怎么办吧 。

就当你需要问那个使用者的姓名的时候 ， 你 ， 你 ， 你使用多个 ， 呃 ， 当你有多 ， 当你有一种并行机制 ，并且你需要解决询问使用者姓名这个问题的时候 ， 你到底应该怎么办 ？

这就是我们接下来需要讨论 ， 讨论的问题 ， 就是异步 IO 最恰当的抽象到底是什么 。

**Rio** [1:34:11]
嗯哼 ， 啊 ， 我们传统上， 比较传统上吧 ， 就可能目前用的 ， 可能大家听得最熟悉的就是一个叫做 asynchronous， 就是异步 IO 这么一个做法 。

这个主要存在于像什么 Node 啊 ， 这种一些 ， 呃 ， 就 Java， 反正是你 ， 你要凡 ， 凡是涉及 JavaScript 的话 ， 基本上都是走 ， 走这种 async IO 的方式嘛 。

然后 Python 的话有这个像 Tornado 啊 ， 还有之前那个叫什么 Twisted， 啊 ， 对 ， 都是这种方式 。 然后 Ruby 里面是有什么 ？

**吴涛** [1:34:43]
Ruby 我还真的不知道 。

**Rio** [1:34:46]
就 Node 它 ， 比如说它底层也是用了像 C 的那个叫 libuv 来实现它的这个异步 IO 的嘛 。

**吴涛** [1:34:52]
对 ， 我记得 NeoVim 它重要 ， 非常重要的那个 to-do 之一就是要把所有的 ， 嗯 ， 呃 ，VI 的那个编辑器里面的 events 都转到 ， 那 Vim 的编辑器里面的 event 都转到 libuv 上实现 。

**Rio** [1:35:08]
啊 ， 对 ， 很多人现在有很多这种采用那个异步 IO 的这种大型程序都在改到用这个包来实现了嘛 ，因为它确实写得很好 ， 什么跨平台那些都做得挺不错的 。

然后 Java 的话有那个叫做 NIO， 就是新 IO 的那么一个库也可以做这种异步 IO 的机制了 。 现在还有什么其他的主流语言呢 ？

好像也差不多了 。

**吴涛** [1:35:33]
对 。

**Rio** [1:35:34]
OK， 然后就是异步 IO 到底是做了一件什么样的事情呢 ？ 就是它们都是在一个很 ， 就是它们都是在一个单进程的情况下去模拟 ， 或者说这么说吧 ， 它们都是在一个单进程的情况下去做一些并发的事情 。

**吴涛** [1:35:52]
对 ， 它们试图用 ，其实就是一个非常简单的 ， 呃 ， 例子 ， 就是我先做一件事情 ， 然后在这件事情跑的间隙之中去做另外一件事情 。

比如说回到我们刚才那个做饭的例子 ， 我 ， 我先把锅坐在火上， 然后开始烧水 ， 然后在烧水的间 ， 间隙里面我开始切菜 ， 然后等到水烧开了 ， 我看到水在滚 ， 然后我再去管烧水的事情 。其实就是一个非常 ， 异步 IO 其实就是这样一个非常简单的问题 ， 只不过它具体实现起来会比做菜这个 ， 这个 ， 这个这么简单的一个任务要复杂很多 。

**Rio** [1:36:33]
对 ， 就为什么说 ， 哎 ， 还有一个问题就是说为什么每次提到异步的时候都一定是指 IO 呢 ？ 因为这个其实牵涉到计算机这个 ， 之前我们某一期讲过计算机体系结构的一个问题 ， 就是说在所有的这个 ， 这个计算机这个应用里面 ， 你只要涉及到 IO 的时候 ， 这个 CPU 都是远远高于 ， 就是它的处理速度是远远高于你这个就是输入输出的速度

的 。 这样的话一个必然的结果就是说 ， 如果你只要一旦涉及 IO 的操作 ， 你的 CPU 就要闲置起来等。

那么异步 IO 的它们一个 ， 一个切入点就是说 ， 那我们就不要等那个 IO 的响应结果回来之 ， 那个一直等它啥等 ， 反正也没 ， 没事做嘛 。

我们在它结果返回来之前 ， 我们先做点别的事 ， 然后等那边结果返回来之后你再通知我 ， 我再回来把这件事情接着再捡起来 ， 啊 ， 接着做下去 。

**吴涛** [1:37:25]
没错 。

**Rio** [1:37:26]
嗯 。

**吴涛** [1:37:26]
呃 ，但是异步 IO 有一个问题 ， 就是很有可能你协调不好 。 呃 。

**Rio** [1:37:33]
对 。

**吴涛** [1:37:34]
就还是用做饭的例子来说 ， 就是可能你想起来 ， 你想当然会觉得哦 ， 烧水的时候我切菜 ，但是你没有办法保证在水烧开之前你一定能把菜切好 。

就是我相信每一个喜欢做饭的人都会有这样的窘境 ， 或者说曾经有这样的窘境 ， 就 ， 就是 ， 就是同时有很多事情要你去 ， 要你去处理 。

甚至我记得新开店英语里面好像有一 ，有一期课文就是这个 ， 就是说一个主妇在和面 ， 然后电话响了 ， 同时， 呃 ， 又有人在敲门 。

**Rio** [1:38:06]
嗯哼 。

**吴涛** [1:38:07]
与此同时再加上如果锅开了 ， 那在这种情况下你该怎么办吧 ？ 那其实异步 ， 异步的 IO， 呃 ， 基于 ， 或者说基于回调的异步 IO， 呃 ， 就有这样的一个与生俱来的问题 。

你 ， 你 ， 你 ， 你很难去 ， 去理解 ， 或者说很难事先判定所有事情的 ， 呃 ， 发生的先后顺序 。 然后因为你 ， 你 ， 你作为一个程序员 ， 你只能用线性的方式去写代码 ， 所以你线性的代码是很难处理这样 ， 呃 ， 一个不知道先后因果顺序的问题 。

**Rio** [1:38:42]
对 ， 就是这里面有一个 ， 通常有个词汇来描述 ， 呃 ， 这个采用异步 IO 的程序结构啊 ， 叫做控制流导致嘛 ，inverse of control flow 嘛 。

**吴涛** [1:38:52]
OK。

**Rio** [1:38:53]
就是说 ， 就是说我们通常写代码的时候都 ， 我们也说 ， 呃 ， 先怎么怎么样 ， 后怎么怎么样 ， 它是一个线性的前因后果的关系走下来的 ， 对吧 ？

但是如果你采用这种异步 IO 这种回调方式来做的话 ， 就会发现 ， 哎 ， 呃 ， 我这个 ， 这个消息过来了 ， 我这个时候该干嘛呢 ？

你得去找 ， 找半天说 ， 哦 ， 我现在到应该到这一步了 ， 我应该恢复到之前那个状态 ， 然后怎么怎么接着做下去 。

就其实是一个 ， 如果人脑去想是一个挺费时费脑的事情 ，但如果你写代码来做的话 ， 就是要考虑很多可能你预想不到的组合的这种情况出现 。

**吴涛** [1:39:28]
没错 。

**Rio** [1:39:29]
啊 ，但异步 IO 的 ， 就是 ， 就基于回调的异步 IO 有一个什么样的好处呢 ？ 就是它可以保证整个这个 ，因为它是一个单进程的这么一个单进程或者单线程的这么一个结构嘛 ， 它一个好处是可以完全不用考虑锁的问题 。

**吴涛** [1:39:45]
对 。

**Rio** [1:39:46]
因为你在任意时刻都只有一个 ， 啊 ， 控制流在执行 。

**吴涛** [1:39:52]
只有一个 ， 只有一个工作单元在跑 ， 一个就是 。

**Rio** [1:39:54]
对 ， 没错 ， 你就不会 ，不用去考虑说我在这个我的这个进程或者线程这个 ， 呃 ， 这个的 ， 就是 memory space， 就是内存空间以内我要去修改任何状态 ， 我不会 ， 我改的时候是肯定是不会有 ，有 ， 任何人跟我抢的 。

**吴涛** [1:40:09]
没错 。

**Rio** [1:40:10]
就这也可能也是有 ， 呃 ， 包括我先讲的 JavaScript 这个 ， 呃 ， 引擎也好 ， 它很 ， 呃 ，在意的一点 ，因为这个你一旦可以避免这个锁或者就同 ， 就 ， 就 ， 呃 ， 就同步叫什么 shared immutable state， 就是共享的可变状态的话 ， 你但可以避 ， 可以避免这个你的整个编程的 ， 嗯 ， 怎么说呢 ， 难度吧 ， 就会降低很大的一个什么数量级的降低 。

但如果你不能 ， 你不能保证这一点的话 ， 你就会牵涉到刚才我们讲的那个并行计算的最核心的矛盾 ， 就是人没有办法去思考 ， 像机器那样并行的去思考嘛 。

**吴涛** [1:40:49]
对 。

**Rio** [1:40:49]
对 ，但是这个基于回调的异步 IO 呢 ， 就是有一个好 ， 一个很大的缺陷 ， 就是它要把我们这个程序整个逻辑流啊 ， 分得非常碎 。

就通过回调的方式 ， 你要把它整个逻辑流做到 ， 啊 ， 切成很多小片段 ， 然后每个片段的它之间的关系又不是非常的那种很线性很明朗 。

这样的话对于你理解整个程序的结构其实是非常不利的 。

**吴涛** [1:41:15]
对 ，在 JavaScript， 呃 ， 程序员里面经常会有这样的笑话 ， 就是 ， 呃 ， 一个回调嵌着另外一个回调 ， 然后再嵌着另外一个回调 ， 然后整个最后你写的代码的结尾就是括号 、 分号 、 花括号 、 括号 、 分号 、 花括号 、 括号 、 分号 ， 这样一层一层嵌套进去 。

对 。

**Rio** [1:41:35]
没错 ， 然后这个有个专门的 ， 我们给它一个称呼叫做回调 ， 回调地狱 ，callback hell。

**吴涛** [1:41:42]
Callback hell。

**Rio** [1:41:43]
对 ， 然后， 呃 ， 就说那我们有没有办法说能够既保留这个单 ， 就是异步 IO 这种单线程不需要考虑锁的机制的好处 ， 同时呢又可以保留我们这个程序逻辑是线性 ，不用分得 ， 呃 ，不用切成小片段 ， 切得很散 ， 就是这种状况呢 ， 就也有一些很 ， 很好的尝试嘛 ， 就是说这个基于协程这么一个概念啊 。

协程是什么意思呢 ？ 刚才讲到有 ，有进程 ，有线程 ，有协程 ， 协程其实是在程序里面自己管理的一个逻辑的 ， 又要用一个广义的进程了哈 。

**吴涛** [1:42:24]
对 ， 我觉得协程其实比较容易理解的 ， 呃 ， 比较容易理解的点就是说 ， 协程其实是非常贴近现实生活的一个东西 。

呃 ， 比如说我在粘模型 ， 然后这个时候女朋友喊我 ， 喊我说 ， 嗯 ， 水开了 ， 你去把它 ， 你去泡个茶 ， 然后我可以很方便的放下我手中的工具 ， 转身去泡茶 ， 回来的时候接着我刚才粘到一半的 ， 呃 ， 的 ， 的 progress，progress， 中文是什么 ？

**Rio** [1:43:01]
呃 。

**吴涛** [1:43:02]
进度 ， 对 ， 呃 ， 然后继续粘我的模型 。 就是说其实现实生活中很多很多事情都是 ， 呃 ， 可以对应到计算机的协程 ，但是在传统的没有协程的编程模型里 ， 编程世界里面 ， 计算机是不知道怎么保存线程的 。

所以说协程其实就是赋予了计算机一种保存一个执行到一半的函数的线程的能力 ， 然后告诉你说你做到这儿给了你一个断点 ， 你可以跳出去做别的事情 ， 回来的时候刚才执行到哪儿还可以继续接着执行 。

这就是协程 。

**Rio** [1:43:37]
所有的你的所谓的 context， 你的上下文都还保留的 ， 保留在那个原样 ， 你可以接着假装没有中断这件事情发生一样 ， 你接着往前走下去了 。

所以其实从这个意义上来讲 ， 线程也好 ， 进程也好 ， 协程也好 ， 它们都是做了同样一件事情 ， 就是说是一段可以被随时重 ， 呃 ， 叫 resume，不叫重启 ， 叫什么 ？

**吴涛** [1:44:00]
呃 ， 恢复 。

**Rio** [1:44:01]
随时可以捡起来接着再做下去的这么一个逻辑 。

**吴涛** [1:44:04]
对 。

**Rio** [1:44:05]
但就唯一的区别就是什么呢 ？ 对 ， 呃 ，resume， 对 ， 没错 。 就是说 ，但它们之间的区别在哪里呢 ？ 就是说 ， 呃 ， 可能在实现的这个 ， 就资源的 overhead 上面是不一样的 ， 可能最重的可能是进程 ，因为操作系统要做很多什么 CPU 寄存器的切换啊 ， 乱七八糟的事情 ， 还要保留一些什么样的转 ， 呃 ， 系统的一些 bookkeeping 的工作 。

**吴涛** [1:44:27]
对 ， 主要是在需要的时候 ， 需要把内存里面的很多数据拷贝一份 ， 这是非常非常大的 。

**Rio** [1:44:33]
对 ， 对 ， 对 ， 然后进 ， 进程的开销呢 ， 就要相 ， 相对要少一点 ，但是还是 ， 还是比较显著的 。

那么协程呢 ， 就是说它直接就绕过操作系统那一步 ， 我直接在程序内部通过一种自制的调度器的方式来管理我自己的那些 ， 呃 ， 呃 ， 那些 task， 那些子任务嘛 ， 然后使得有一个非常 ， 呃 ， 轻量的资源的开销 ， 同时又能给我带来像类似于进程或者线程那样的一个 ， 嗯 ， 线性的逻辑流的好处吧 。

**吴涛** [1:45:04]
对 ， 这样前面所提到的这种 inverse of control flow 的问题就不会 ，不会再发生了 。

**Rio** [1:45:09]
没错 。

**吴涛** [1:45:10]
对 。

**Rio** [1:45:11]
呃 ， 现实中使用协程的例子也是蛮多的哈 ， 尤其是 ， 呃 ， 呃 ， 总体来讲像 GoLang 的那个 GoRoutine 嘛 ， 它就是一种协程的一种 ， 一种吧 ， 一种变种 。

然后像 Python 的话 ， 它有一个叫做 generator 生成器这么一个概念 ， 就是它 ， 它这个函数里面是有一个特殊的关键 ， 那个关键词叫做 yield， 可以暂时的让出 ，yield 就是让出的意思嘛 ， 让出这个程序的控制流 ， 然后等那边 ， 呃 ， 条件合适的时候你再把它回到这个位置 ， 然后接着从这个点往下执行 。

然后我知道是 JavaScript 从应该是下一个版本还是 ， 还是 7 的时候它也在加 ， 啊 ，不 ， 就下一个版本加 ， 加就是 EmacScript 6，EmacScript 6 这个版本里面就已经有这个 ， 呃 ， 类似的 generator 这么一个概念在里面了 。

然后 Ruby 的话 ， 它有一个分 ，有一个特性叫做 fiber 吧 ，也是一个协程的例子 。

**吴涛** [1:46:08]
对 ，fiber 一般翻译成叫什么 ？ 纤程 ， 就是比线程更要细的纤维 ， 纤程 ，但实际上纤程就是协程 。

**Rio** [1:46:17]
因为它是对应那个 thread 来的 ，thread 在那个织布的那个 ， 那个概 ， 那个语境 ， 就是纺织业的语境里面是叫什么 ？

线头 ， 对不对 ？

**吴涛** [1:46:24]
对 ， 一根线 ，而 fiber 则是组成这个线的一根纤维的纱 。

**Rio** [1:46:29]
一根纱嘛 ， 对 。

**吴涛** [1:46:30]
没错 。

**Rio** [1:46:30]
就是这个 ， 这个意思 。 嗯 ， 然后 Python 的话还有一个 ， 嗯 ，有个 fork 吧 ， 算是叫做 gEvent， 它是可以甚至通过那种方式来做 ， 呃 ， 全局的 ， 呃 ， 协程 ， 呃 ， 这个协程 ，而不是说只仅局限于这个 generator 这种比较受限的协程 。

**吴涛** [1:46:51]
OK， 所以 。 但问题在于不管是回调还是协程 ， 都没有办法非常有效的利用多核处理器补什么 ，因为你 ， 你所谓你无论如何都只有一个单 ， 只有一个单个的进程 。

**Rio** [1:47:05]
嗯 ， 没错 ， 一般是这样子的 ， 比如刚才我们谈到那几个例子 ， 它都是因为有这样那样的限制导致它不能使用多线程 ，但是也并不完全是这样 。

就是说比如说 Go 的那个 GoRoutine， 它其实是可以利用多线 ， 那个多个处理器核心的 ， 就是看你这个系统的调度的时候你是怎么去调度它而已 。

**吴涛** [1:47:26]
OK。

**Rio** [1:47:27]
啊 ， 然后还有像 Erlang 这种比较诡异的例子 ，但它有非常独特的一种机制 ， 它 ， 它里面的线程不是系统的线程 ， 它是自己 ， 自己内置的线程 ， 它也并不 ，但也它也并不是一个协程 ， 就它每个线程都是完全独立 ， 就是没有任何和其他共享资源的地方 。

就是说它的那个调度其实可以很方便的去管理它那些 ， 那些 ， 呃 ， 叫做执行的步骤嘛 ， 它们叫做 reduction 这么一个 ， 一个步骤 。

**吴涛** [1:47:56]
对 ，Erlang 我虽然不是很了解 ，但我觉得它的 ， 它的思路基本上就是把 thread 当做一种语言内在的机制 ，而不是对操作系统提供的机制的一种抽象 。

**Rio** [1:48:08]
没错 。

**吴涛** [1:48:09]
呃 ，因为 ，因为它使用的那个 ， 那个 actor，actor model，actor 模型对这种事情是有天然的需求的嘛 ，而且它整个 ， 啊 ， 这个调度器也好 ， 解析器也好 ， 都是为这种方式去 ， 去优化的 。

虽然说它的可能整 ， 就是执行某一个这种就是所谓的就 CPU heavy 的东西的性能不怎么样 ，但是它对这种 ， 啊 ， 可以并行计算的任务的处理是非常非常优秀的 。

没错 。

### 学习语言

**吴涛** [1:48:37]
呃 ， 对 ，其实我现在在学 Haskell， 终于开始 ， 或者说终于又开始 。

**Rio** [1:48:41]
为什么突然有这个契机去学它 ？

**吴涛** [1:48:45]
啊 ， 我也不知道 ， 就是可能主要契机还是因为之前看的那个 Objective-C 的 ， 呃 ，blog， 嗯 ， 它们 。

**Rio** [1:48:55]
受其蛊惑 ， 对不对 ？

**吴涛** [1:48:56]
对 ， 它们提供了大量的 ， 呃 ， 奇技淫巧 ， 就是为了让你写 Swift 的时候看起来更像 Haskell， 我觉得何必呢 ， 那我干脆去学一学 Haskell 好了 。

但这样的 ， 这样的 ， 这样的尝试已经有过很多次 ，但我每次都没有坚持下来 ， 我觉得这次应该坚持坚持 。

然后在那之后我也许可以试试 Erlang，因为有呢 ，在我北边有一个城市叫做 Erlangen， 我以前 ， 我以前写过一个 ， 写过一条推 ， 就是说 ， 呃 ，Erlangen 这个地方就是由 ， 呃 ， 二战时期被纳粹集中在一起的 Erlang 程序员建立的 ， 所以它叫做 Erlangen，在德语里面就是使用 Erlang 编程的意思 。

**Rio** [1:49:39]
哈哈 ， 对 。 哎 ，Erlangen 在德语里面什么意思 ？ 没有意义吗 ？ 还是只是个名字而已 ？

**吴涛** [1:49:46]
嗯 ， 没有什么意义吧 ， 就至少我找不出什么特别 ， 呃 ， 至少我想不到什么特别明显的语言 。 我回头会去查一下 etimology，但我可以基本上可以确定 Erlangen 跟 Erlang 没有任何 ， 没有任何关系 。

**Rio** [1:49:59]
因为 ，因为 Erlang 里面那个也很 ， 很简单 ， 它是那个爱立信的实验室做的语言嘛 ， 叫做 Arixon language， 所以是 Erlang。

**吴涛** [1:50:07]
啊 ， 原来是这么来的 。OK。

**Rio** [1:50:09]
你不知道 ？

**吴涛** [1:50:10]
不知道啊 ， 就我对 Erlang 的理解非 ， 理解了解非常非常有限 。

**Rio** [1:50:14]
对 ， 它就是这么样 ，而且它有一个 ， 啊 ， 这个 ， 这个可能之后有一期专门讲 Erlang 的时候再说吧 ， 还有一个很有意思的那个 ， 就看起来甚至有点 weird 的一个短视频 ， 非常有意思 。

**吴涛** [1:50:26]
嗯哼 。

**Rio** [1:50:27]
就是它们 ，因为 Erlang 最开始的用途是用于做那个叫做什么 ， 呃 ， 电话交换机的控制的嘛 。

**吴涛** [1:50:34]
对 。

**Rio** [1:50:34]
就控制拨号啊 ， 然后怎么怎么样 ， 然后它就用 ， 它的那个视频就整个过程都在描述这么一个过程中这个 Erlang 是怎么样起作用的 ， 非常好笑的一个视频 ， 一定要看一下 。

有一种 Monkey Python 的既视感 。

**吴涛** [1:50:48]
啊哈 ，有意思 。 所以处理电话拨号其实是听起来也是一个天生就带有并发性质的问题领域 。

**Rio** [1:50:58]
嗯哼 ， 没错 。

**吴涛** [1:50:59]
对 ， 所以在从这样一种领域里面所为了解决这样一个领域的问题而诞生的编程语言也就天生的非常强调解决这种问题的方便程度 。

**Rio** [1:51:12]
嗯哼 ，而且我觉得它 ， 它这个就是 Erlang 它这种方式 ，而且采用它 ， 它 ， 它采用的这种像 actor model 也好 ， 还是它这种自己的这种调度器也好 ， 它有一个很成熟的叫做监控的系统 ，supervision system， 叫做 OTP 嘛 ， 就是 Open Telecom Platform， 开放电信平台 ， 听起来很怪哈 ， 为什么会是电信 。

**吴涛** [1:51:34]
听起来非常电信 。

**Rio** [1:51:36]
对 ， 听起来非常爱立信 。 但是它 ，但是它确实是解决了很多这种大型软件工程的一些问题 ， 比如说它里面的所有的那些 ， 那些就是线程嘛 ， 我们叫做 actor 也好 ， 它是随时可以 ， 可以让它 ， 就是它的错误处理机制是不处理 ， 让它 ， 让它 crash 掉 。

**吴涛** [1:51:53]
嗯 。

**Rio** [1:51:54]
然后 crash 掉之后怎么办呢 ？ 它每一个 actor 它会为它分配一个叫做 supervisor，supervisor 就是监管管理者 ， 然后这个管理者不叫 ，不叫每一个 ，不是 ，不是 ， 就是说 ， 呃 ， 这里说错了 ， 应该重新讲一下， 应该说它里面每一个 actor 都是被一个 supervisor 管理的 。

如果这个 supervisor 探测到那个 actor 挂掉了 ， 它就会 ， 或者死掉了 ， 它就会重新再起一个一模一样的 。 然后它里面整个这种 ， 这 ， 这一套思维哲学是非常 ， 非常 ， 呃 ， 很不一样 。

而且你到目前为止我们做那种很多这种像做那种大规模的分布式系统的维护的时候会发现 ， 越你做的系统越大 ， 你越会 ， 你的那个什么整个架构会越靠近像那个 Erlang 的这种 ， 这种这套模型来讲 。

比如说很简单的一个那个 Google 的那个例子吧 ， 那 Google 来说它们就传统上我们做这种 ， 呃 ， 服务器软件 ， 我们都要考虑说啊 ， 我们这个 ， 这个服务器不要挂掉 ， 我们要它高稳定可靠 ， 对吧 ？

就好像我们说这个服务器的可靠性要高于工作站的 ， 然后工作站的可靠性要高于这种个人 PC 的 。

但是你为了换取那更高可靠性 ， 你要付出更高的成本啊 ， 就单位硬件或单位计算能力的成本你是要上去了嘛 。

然后 Google 当年的做法就是说啊 ， 我们做大规模的这种 ， 这种服务端 ， 我们不需要用这种所谓的服务 ， 就是 server grade hardware， 就是服务器级别的硬件 ， 什么高档处理器啊 ， 或者是高档机房啊 ， 这种东西 ， 我们就用普通的所谓的 commodity hardware， 就是这种 。

**吴涛** [1:53:26]
随处可见的唾手可得的普通机器 。

**Rio** [1:53:29]
就普通机器 ， 就可以随意替换的机器 。 然后它虽然说它的那个故障率要比这种所谓的服务器级别的硬件要高 ，但是我们只要把软件的容错写好 ， 我们它随时挂掉任何几个机器都是没有 ， 没有不影响我们这个系统整个系统运作的嘛 。

然后你要实现这一点 ， 你就会发现你会越来越的类似用到类似于 Erlang 的那种机 ， 那种机制 ， 要去监控 ， 然后要去 ， 呃 ， 假设错误是不可恢复的 ， 然后你要如果遇到错误 ， 你就要重新起一个新的节点来接替之前挂掉的那些节点的工作 ， 那诸如此类的事情吧 。

**吴涛** [1:54:05]
对 ， 就我脑中浮现出了早期电话系统那种 ， 呃 ， 一排接线机器前面坐着一大 ， 呃 ， 坐着很多接线员的场景 。

然后一个 supervisor 在那边看说这个接线员累倒在了工作岗位上， 立刻把他撤走 ， 换另外一个来插 ， 插线头 。

**Rio** [1:54:25]
感觉是血 ， 血汗工厂 。

**吴涛** [1:54:27]
没错 。其实这也就说到这个也就想到了上一期我们跟博洋聊的 ， 说他问我们你们学 Haskell 的动机是什么 ， 那或者说那学 ， 啊 ， 那我觉得可以把这个问题又泛化为学 Erlang 或者是 Haskell 这种比较加引号小众的编程语言 ， 它的 ， 它的比较 ， 比较功利的一个 ， 一个效果就是你可能会发现 ， 当你需要解决一个特定领域的问题的时候 ， 你会发现在这种比较小众的

语言里面已经有了相当好的解决方案 ， 已经有了 ， 嗯 ， 已经有先人对此深思熟虑过 ，并且设计出了一个非常好的模型 。

那么当你在 ， 当你在用你的所谓原生语言去解决它的时候 ， 就会方便很多 。

**Rio** [1:55:19]
对 ， 就甚至说你不一定真的用到这个 ， 这个语言的具体的实现 ， 甚至你都不会用这个语言去写 ， 去写新的代码 ，但是你从这里面学到的这种思想可能会有助于你在现有的工作中去提升你的这个架构的能力也好 ， 或者说是你去抽象事物的能力 ， 你会发现 ， 哎 ， 原来还可以从这个角度去思考问题 ， 对吧 ？

**吴涛** [1:55:41]
对 ， 这个为什么人要去做 ， 你要去努力做一个 polyglot， 这就好像你多学一个捷克有个谚语嘛 ， 就是你 ， 你会几种语言你就有几种人生 。

所以在编程领域其实也是这样的 ， 你会几种语言你就可以 ， 你就多会几种语言你就可以多理解几种编程模型 。

**Rio** [1:56:01]
你看看吧 ， 参差多态才是美 ， 这里又体现出来了 。

**吴涛** [1:56:05]
没错 。

**Rio** [1:56:07]
嗯 ， 差不多了 。 好吧 ， 今天你也结尾一下吧 。

### 结语

**吴涛** [1:56:13]
嗯 ， 对 ， 所以今天我们大概就讲述了 ， 当然可能不是非常的满意 ，因为做了很多 ， 呃 ， 解释一些比较复杂的问题的尝试 ，但是都没有能 。

**Rio** [1:56:28]
很小 ， 失败了 。

**吴涛** [1:56:30]
对 ， 都没有能做得很好 。 这可能也从另外一个侧面反映出了 ， 嗯 ， 并发和异步其实的确是在编程领域比较难的一些问题 。

**Rio** [1:56:41]
嗯哼 。 但也有 ，也有可能说明我们俩 ， 我们两个太水 。

**吴涛** [1:56:46]
这是肯定的 。 我从来不怀疑 。

**Rio** [1:56:49]
那 ， 那句话怎么说来着 ， 就是说 ， 啊 ， 如果你能够用几句话的东西真能给人家 ， 或者说你能够很清晰明白的给人家解释一个东西 ， 那么你对这个事情的理解就肯定是比较透彻了 。

但如果你解释不了 ， 很有可能是你自己理解的还不够深刻 。

**吴涛** [1:57:04]
对 ， 就是有很多东西都会有这样一个阶段 ， 就是你以为自己懂了 ，但是当你要向别人解释的时候 ， 会发现自己其实并不是真的理解 。

嗯 ， 对 ， 从这个侧面来说 ， 我觉得可能做 Podcast 对 ， 对 ，不知道你 ，但对我来说是也是一个非常大的帮助 ， 就是 ， 呃 ， 就像之前我在知乎答案里面说过那样 ， 就是非常帮助我去把自己之前可能一知半解的部分弄得比较 ， 比较二知一解 ， 就是把它为了向 ， 为了做好一些节目 ， 可能我会去看一些相关的书啊 ， 这些对于我来说也是非常大的帮助 。

**Rio** [1:57:46]
不光是这个 ， 就是不管你是在 ， 呃 ， 说 ， 就是口述也好 ， 还是说笔头写下来也好 ， 就是你整个在输出的过程其实就是在考验你内部的那个什么知识的组织也好 ， 还是你的理解也好 ， 对吧 ？

都是它对你是一个 ， 是一个 ， 呃 ， 使用的过程 。 这个时候你会发现 ， 啊 ， 如果你的某 ， 对某一点理解不够透彻的话 ， 你这是没有办法解释清楚的 。

**吴涛** [1:58:11]
对 ， 所以 ， 呃 ，也希望这一期节目能够起到抛砖引石的作用 。 如果哪位听众对于 ， 呃 ， 异步和并发有比较深刻的理解 ， 然后觉得一些我们没有讲清楚乃至讲错的概念可以 ， 啊 ， 值得纠正的话 ， 那也欢迎你写信给我们 。

我们的 ， 嗯 ， 电子邮件地址是 kernelpanic@ipn.li， 然后也欢迎你拨打我们的热线电话 0118 999 881 999 119 7253。

**Rio** [1:58:46]
哈哈哈 。

**吴涛** [1:58:48]
好 。 如果你非常喜欢我们的节目 ， 或者说不管你是不是喜欢我们的节目 ， 都欢迎你为我们捐款 。

呃 ， 捐款的地址是 kernelpanic.fm/donate。 金额随意 ，但必须是可以被 8 整除的正整数 。 然后， 嗯 ， 为了向现代计算机的基础组成 Byte 致敬 ， 我们把它设定为至少要被 8 整除 。

嗯 ， 好吧 ， 那今天就到这了 。

**Rio** [1:59:19]
OK。

**吴涛** [1:59:20]
嗯 ， 对 ， 感谢收听 。

**Rio** [1:59:22]
下期再见 。

**吴涛** [1:59:22]
下期再见 ， 拜拜 。

---

本节目库由 PodHood（https://podhood.com）提供支持——播客网站平台。
