简介
新硬件的并行性越来越强,因此新的编程语言必须支持并发性,否则就会消亡。
“处理器行业的发展方向,是增加越来越多的核心,但没有人知道如何对这些东西进行编程。我的意思是,两个,可以;四个,不行;八个,算了吧。” --苹果公司史蒂夫-乔布斯1
史蒂夫错了;我们确实知道如何为多核编程。我们用 Erlang 对他们进行编程,而咱们的许多程序,都会随着内核的增加而变得更快。
自底向上,Erlang 都是为并发、分布式、容错、可扩展的软实时系统编程而设计。所谓软实时系统,是指诸如电话交换机、银行系统等的一些系统,其中快速响应时间非常重要,但即使错过了零星的定时截止时间,也不会造成灾难。一些 Erlang 的系统,已被大规模部署,并控制着世界上移动通信网络的重要部分。
如果咱们的问题是并发的,如果咱们正构建某个多用户系统,或者如果咱们正构建某个随时间演进的系统,那么使用 Erlang 可能会为咱们节省很多工作,因为 Erlang 正是专门为构建此类系统而设计的。
“这是可变的状态,愚蠢。” -- Brian Goetz,Java 并发实践
Erlang 属于 函数式编程语言 家族。函数式编程禁止带有副作用的代码,functional programming forbids code with side effects。副作用和并发性不相容。在 Erlang 中,于单个进程内改变状态是可以的,但一个进程不能改变另一进程的状态。Erlang 没有互斥,没有同步方法,也没有共享内存编程的任何工具。
进程间交互有且只有一个方法,即交换消息/报文, by exchanging messages。进程不与其他进程共享数据。这就是为什么我们可以轻松地在多核或网络上,发布 Erlang 程序的原因。
当我们编写某个 Erlang 程序时,我们并不是将其作为一个完成所有事情的单独进程实现,而是将其实现为大量的,完成一些简单事情并相互通信的小进程。
这本书讲的是什么?
这是有关并发的、有关分布式、有关容错、有关函数式编程的一本书。这是关于不使用锁和互斥,而只使用纯消息传递的分布式并发系统编程的一本书。这是有关在多核 CPU 上,自动加速咱们程序的一本书。这是有关编写允许人们交互的分布式应用程序的一本书。这是有关编写容错与分布式系统设计模式的一本书。这是有关并发建模,以及将这些模型映射到计算机程序,我(作者)将这一过程称为 面向并发的编程,concurrency-oriented programming。
- concurrency
- distribution
- fault tolerance
- functional programming
- locks and mutexes
- message passing
- design patterns
- distributed systems
- modeling concurrency
- concurrency-oriented programming
这本书适合哪些人阅读?
本书的目标读者,包括希望进一步了解 Erlang 内部结构于 Erlang 背后理念的资深 Erlang 程序员,以及绝对的初学者。从专家到初学者,各个层次的专业程序员都对本书进行了审阅。第二版与第一版的主要区别之一,是增加了大量的解释性材料,特别针对初学者。高级 Erlang 程序员可以跳过入门材料。
本书的第二个目标是揭开函数式、并发与分布式编程的神秘面纱,并以一种适合尚无并发或函数式编程知识的读者方式,介绍这些知识。长期以来,编写函数式程序与并行程序,一直被视为一门 "黑色艺术";本书正是为改变这一现状而不断尝试的一部分。
虽然本书并未假定对函数式编程或并行编程有具体的了解,但他面向的读者,是那些已熟悉一两门编程语言的人。
当咱们来到一门新的编程语言时,往往很难想到 "适合用新语言解决的问题"。这些练习为咱们提供了线索。这些都是适合用 Erlang 解决的问题。
这一版本中的新内容
首先,我们对文本进行了更新,以反映自本书第一版出版以来 Erlang 发生的所有变化。现在,我们涵盖了语言官方的所有变更,并介绍了 Erlang R17 版本。
译注:如今(2025-8-14), Erlang 的版本为
Erlang/OTP 28
。
第二版重新调整了重点,以满足初学者的需求,与第一版相比增加了解释性文字。面向高级用户或可能快速变化的资料,已移至在线代码仓库。
编程练习在第一版中大受欢迎,现在每章末尾都有练习。这些练习的复杂程度各不相同,因此无论是初学者还是高级用户,都能找到适合自己的练习。
在几个全新的章节中,咱们将了解 Erlang 的类型系统与 Dialyzer、映射(Erlang 在 R17 中新增功能)、websockets、编程习语以及集成第三方代码。一个新附录介绍了如何构建最小独立的 Erlang 系统。
最后一章 “夏洛克的最后一案” 是个新的章节,为咱们提供了一个从大量文本中,处理并提取意义的练习。这是个开放性的章节,我(作者)希望本章末尾的练习,能激发今后的工作。
路线图
在学会走路前是没办法跑起来的,我们要循序渐进。Erlang 程序是由许多同时运行的小的顺序程序组成的,Erlang programs are made up from lots of small sequential programs running at the same time。在咱们能编写并发代码前,我们需要能够编写出顺序代码。这意味着我们要到 第 11 章 真实世界的并发,Real-World Concurrency,才会涉及编写并发程序的细节。
- 第一部分简要介绍了并发编程的核心思想,并对 Erlang 进行了旋风式的介绍;
- 第二部分详细介绍了顺序的 Erlang 编程,还讲述了构建 Erlang 程序的一些类型与方法;
- 第三部分是本书的核心,其中我们将学习如何编写并行与分布式的 Erlang 程序;
- 第四部分介绍了一些主要的 Erlang 库,一些跟踪与调试技巧,以及 Erlang 代码结构化的技巧;
- 第五部分涉及应用程序。咱们将学习如何将外部软件与核心的 Erlang 库集成,以及如何将自己的代码转化为开源贡献。我们将讨论一些编程习语,以及如何为多核 CPU 编程。最后,福尔摩斯将分析我们的想法。
在每章末尾,咱们都会看到精选的编程练习。这些练习旨在测试咱们对该章知识的掌握程度,并向咱们提出挑战。这些问题由易到难。最难的问题适合作为研究项目。即使咱们不尝试解答所有问题,但只要思考这些问题以及如何解决他们,就会加深对课文的理解。
本书中的代码
大多数代码片段,都来自咱们可下载的完整运行示例。2 为帮助咱们找到方向,如果本书中的某个代码列表可在下载中找到,代码片段上方会有一个条形图(就像这里的一样):
-module(shop1).
-export([total/1]).
total([{What, N}|T]) -> shop:cost(What) * N + total(T);
total([]) -> 0.
条形图包含了该代码在下载中的路径。如果咱们正在阅读本书的电子书版本,并且咱们的电子书阅读器支持超链接,那么咱么可以点击该栏,代码就会出现在浏览器窗口中。
救命!这不工作
学习新知识很困难。咱们会被卡住。当咱们被卡住时,规则 1 是不要默默放弃;规则 2 是寻求帮助;规则 3 是向福尔摩斯请教。
规则 1 非常重要。有些人尝试过 Erlang,卡住了,放弃了,却没有告诉任何人。如果我们不知道问题所在,我们就无法解决他。故事结束。
获得帮助的最佳方法,是先尝试 Google;如果 Google 无法提供帮助,请向 Erlang 邮件列表发送邮件 3。咱们也可尝试在 irc.freenode.net 上的 #erlounge,或 #erlang 下获取更快的回复。
有时,咱们问题的答案可能就在 Erlang 邮件列表的旧贴中,但咱们就是找不到。在 第 27 章 “夏洛克的最后一案” 中,有个咱们可在本地运行的程序,他可以对 Erlang 邮件列表中的所有旧贴,进行复杂的检索。
因此,事不宜迟,我(作者)要感谢帮助我写这本书(和第一版)的好人,咱们可以跳到第1章,在那里我们将参加 Erlang 的闪电之旅。