UP | HOME

并发介绍

Table of Contents

现实世界

让我们暂时忘却编程,思考一下现实世界里发生着什么 

我们理解并发

我们的大脑天生就对并发有着深刻的理解。大脑里一个名为杏仁核的区域让我们能迅速对刺激作出反应。如果没有这种反应,我们就会死亡。意识思维实在是太慢了,当“踩下刹车”这个念头形成时,我们已经这么做了

当我们驾车行驶在主干道上,脑子里会时刻定位着数十甚至数百辆车。这是在没有意识思维参与的情况下做到的。如果我们做不到这一点,多半就没命了

世界是并行的

如果我们想让编写的程序有着现实世界里其他对象的行为,这些程序就会是并发架构的。这就是我们应该用并发编程语言来编写程序的原因

然而,我们经常用顺序编程语言来编写现实世界里的应用程序。这样做会带来不必要的困难

如果使用一种为编写并发应用程序而设计的语言,进行并发开发就会简单得多

Erlang进程

我们没有共享“内存”(也就是记忆)。我有我的记忆,你有你的记忆。我们各有一个大脑,它们并不相连

为了改变你的记忆,我会向你发送一个消息:通过说话,或者挥舞手臂

你倾听,观察,然后改变了记忆

但是,如果不问你问题或者观察你的反应,我就无法知道你是否收到了我的消息 

这就是Erlang进程的工作方式:

  • Erlang进程 没有共享内存 ,每个进程都有它自己的内存。要改变其他某个进程的内存,必须向它 发送 一个 消息 ,并祈祷它能收到并理解这个消息
  • 确定 另一进程 收到了你的消息改变了它的内存 ,就必须 询问 它(通过向它发送一条消息)
这就是我们的交流方式:

苏:嗨,比尔,我的电话号码是345-678-1234 
苏:你听到了吗?
比尔:是的,你的电话是345-678-1234 

一个Erlang程序会包含几十、几千、甚至几十万个小进程。所有这些进程都是独立运作的。它们通过发送消息来相互交流。每个进程都拥有一块私有内存区域

它们表现得就像是一大群人在一个巨大的房间里喋喋不休 

这使得Erlang程序天生 易于管理和扩展

假设我们有10个人(进程),而他们有太多的工作要做,我们可以怎么办? 找更多的人过来

我们要如何管理这群人?很简单:大声把命令告诉他们(广播)就可以了

Erlang进程不共享内存,因此使用内存时 无需加锁

有锁的地方就会有钥匙,而钥匙是容易丢失的

当你丢了钥匙会发生什么?你会惊慌得不知所措

当你在软件系统里丢了钥匙,使锁出现问题时也会如此

分布式软件系统里只要有锁和钥匙,就总会出问题

错误检测

如果我在一个房间里突然倒下死去,很可能就会有人注意到(好吧,至少我希望如此)

Erlang进程就像人类一样,有时会死去。但和人类不同的是,当它们死亡时,会用尽最后一口气喊出导致它们死亡的准确原因

想象一个挤满人的房间里突然有一个人倒下死去。就在那一刻,他说“我的心脏病发作了”或者“我吃得太多,胃爆炸了”

Erlang进程就是这么做的。一个进程可能会在临死时说:“我是因为有人要求我除以零而死的。”另一个可能会说:“我是因为有人问我空列表的最后一个元素是什么而死的。“

现在,在这个挤满人的房间里,我们可以设想有些人被特别指派从事清理尸体的工作

让我们假设有简和约翰两个人:
如果简死了,约翰会处理一切与简的死亡有关的问题
如果约翰死了,简会处理这些问题
简和约翰通过一种不可见的约定连接在一起,这个约定是如果其中一人死亡,另一人就会处理一切由此产生的问题

Erlang的 错误检测 正是使用的这种方式。进程可以 相互连接 :如果其中一个进程挂了,另一个进程就会得到一个说明前者死亡原因的错误消息

总结

Erlang程序就是这么工作的:

  • Erlang程序由大量进程组成。这些进程间能相互发送消息
  • 这些消息也许能被其他进程收到和理解,也许不能。如果想知道某个消息是否已被对方
  • 进程收到和理解,就必须向该进程发送一个消息并等待回复
  • 进程可以成对相互连接。如果某一对互连进程的其中一个挂了,另一个进程就会收到一个说明前者死亡原因的消息
这个简单的编程模型是一个大模型的一部分,我把这个大模型称为”面向并发编程“

下面将开始编写并发程序。我们需要学习三个新的基本函数: spawn 、 send(使用 ! 操作符)和 receive 。然后就能编写一些简单的并发程序了。

如果一个进程挂了,另一个进程(如果与前者相连的话)就会注意到

Next:并发原语

Home:目录