Bell Labs and CSP Threads

介绍

本页是并发编程历史的一部分,重点介绍了 Hoare 的通信顺序进程 (CSP) [1] [1a]语言的一个特定血统。这种风格的并发编程很有趣,不是因为效率,而是因为清晰。也就是说,仅将并发编程视为提高性能的一种手段是一个普遍的错误, 例如,重叠磁盘 I/O 请求,通过将结果预取到预期查询来减少延迟,或者利用多个处理器。这些优势很重要,但与本次讨论无关。毕竟,它们可以以其他方式实现,例如异步事件驱动编程。相反,我们对并发编程很感兴趣,因为它提供了一种自然的抽象,可以使一些程序变得更简单。

这不是什么

大多数计算机科学本科生被迫阅读 Andrew Birrell 的 “线程编程简介”。 SRC 线程模型是当前可用的大多数线程包使用的模型。所有这些的问题是它们太低级了。与 Hoare 提供的通信原语不同,SRC 风格的线程模块中的原语必须与其他技术(通常是共享内存)结合才能有效使用。一般来说,程序员倾向于不构建他们自己的更高层次的结构,并且因为需要关注这些低层次的细节而感到沮丧。

暂时,把 Birrell 的教程从你的脑海中抹去。这是一个不同的线程模型。如果您将其视为不同的线程模型,您可能会发现它更容易理解。

通信顺序过程

到 1978 年,在多处理器编程的环境中,已经提出了许多用于通信和同步的方法。共享内存是最常见的通信机制,信号量、临界区和监视器属于同步机制。CAR Hoare 使用单一语言原语解决了这两个问题:同步通信。在 Hoare 的 CSP 语言中,进程通过从命名的无缓冲通道发送或接收值来进行通信。由于通道是无缓冲的,因此发送操作会阻塞,直到将值传输到接收器,从而提供了一种同步机制。

Hoare 的例子之一是重新格式化 80 列卡片以在 125 列打印机上打印。在他的解决方案中,一个进程一次读取一张卡片,将反汇编的内容一个字符一个字符地发送到第二个进程。第二个过程组装 125 个字符的组,将这些组发送到行式打印机。这听起来微不足道,但在没有缓冲 I/O 库的情况下,单进程解决方案所涉及的必要簿记是繁重的。实际上,缓冲 I/O 库实际上只是对这两种导出单字符通信接口的进程的封装。

作为另一个例子,Hoare 将其归功于 Doug McIlroy,考虑所有小于一千的素数的生成。Eratosthenes 的筛子可以通过执行以下伪代码的流程管道来模拟:

p = 从左邻居获取一个数字
print p
循环:
n = 从左邻居获取一个数字
如果(p 不除 n)
将 n 发送到右邻居
生成进程可以将数字 2, 3, 4, …, 1000 输入管道的左端:行中的第一个进程消除 2 的倍数,第二个消除 3 的倍数,第三个消除5的倍数,以此类推:

到目前为止,示例的线性流水线性质错误地代表了 CSP 的一般性质,但即使仅限于线性流水线,该模型也非常强大。Unix 操作系统众所周知的过滤器和管道方法的成功有力地证明了这种能力 [2] 事实上,管道早于 Hoare 的论文。在 1964 年 10 月 11 日的贝尔实验室内部备忘录中,Doug McIlroy 正在玩弄将成为 Unix 管道的想法:“我们应该有一些方法来耦合程序,比如花园软管——当需要在另一种方式。这也是 IO 的方式。” [3]

Hoare 的通信进程比典型的 Unix shell 管道更通用,因为它们可以以任意模式连接。事实上,Hoare 给出了一个 3x3 矩阵的例子,它有点像素筛,可用于将向量乘以 3x3 方阵。

当然,Unix 管道机制不需要线性布局;只有 shell 语法可以。McIlroy 报告说,他在早期就玩弄了一个带有通用管道的 shell 的语法,但不喜欢语法来实现它(个人交流,2011 年)。后来的 shell 确实支持一些受限形式的非线性管道。Rochkind 的 2dsh 支持 dags;Tom Duff 的 rc 支持树。

霍尔的语言新颖而有影响力,但缺乏一些关键方面。主要缺陷是用于通信的无缓冲通道不是一流的对象:它们不能存储在变量中、作为参数传递给函数或跨通道发送。因此,在编写程序时必须固定通信结构。因此,我们必须编写一个程序来打印前 1000 个素数而不是前n 个素数,并将向量乘以 3x3 矩阵而不是n x n矩阵。

潘和普罗梅拉

1980 年,在 Hoare 的论文发表仅仅两年后,Gerard Holzmann 和 Rob Pike 创建了一个名为 pan 的协议分析器,它以 CSP 方言作为输入。Pan 的 CSP 方言有连接、选择和循环,但没有变量。尽管如此,Holzmann 报告说“Pan 在 1980 年 11 月 21 日在贝尔实验室的数据交换控制协议中发现了它的第一个错误。” [14]。这种方言很可能是贝尔实验室的第一个 CSP 语言,它无疑为 Pike 提供了使用和实现类似 CSP 语言的经验,这是他的第一个。

Holzmann 的协议分析器发展成 Spin 模型检查器及其 Promela 语言,它以与 Newsqueak (qv) 相同的方式具有一流的通道。

新闻快报

朝着不同的方向发展,Luca Cardelli 和 Rob Pike 将 CSP 中的想法开发成 Squeak 迷你语言 [4] 以生成用户界面代码。(此 Squeak 与 Squeak Smalltalk 实现不同。)Pike 后来将 Squeak 扩展为成熟的编程语言 Newsqueak [5] [6] ,它产生了 Plan 9 的 Alef [7] [8]、Inferno 的 Limbo [9]和 Google 的去 [13]。Newsqueak 相对于 Squeak 的主要语义优势在于 Newsqueak 将通信渠道视为一流的对象:与 CSP 和 Squeak 不同,渠道 可以 存储在变量中,作为参数传递给函数,并跨通道发送。这反过来又使通信结构的程序化构建成为可能,从而允许创建比手工设计更复杂的结构。特别是,Doug McIlroy 演示了如何使用 Newsqueak 的通信设施来编写优雅的程序来操纵符号幂级数 [10]。传统语言中的类似尝试往往会陷入簿记。与此类似,Rob Pike 演示了如何使用通信设施来突破常见的基于事件的编程模型,编写并发窗口系统 [11]。

阿莱夫

Alef [7] [8] 是 Phil Winterbottom 设计的一种语言,用于将 Newsqueak 的思想应用于成熟的系统编程语言。Alef 有两种我们一直称为进程的类型:过程和线程。该程序被组织成一个或多个procs,它们是可以抢先调度的共享内存操作系统进程。每个 proc 包含一个或多个任务,它们是协作调度的协程。请注意,每个任务都分配给特定的 proc:它们不会在 procs 之间迁移。

procs 的主要用途是提供可以独立于主要任务阻塞 I/O 的上下文。(计划 9 没有选择调用,即使在 Unix 上,如果您想与非网络 I/O 重叠计算,您也需要多个 proc。)Acme 论文 [12]对 proc 和线程进行了 很好的简短讨论,就像 关于 Plan 9 窗口系统的讲义,下面也会提到。

凌波

Inferno 操作系统是计划 9 的衍生产品,旨在用于机顶盒。它的编程语言 Limbo [9]深受 Alef 的影响。它消除了过程和任务之间的区别,实际上只有过程,尽管它们比大多数人认为的过程更轻。所有并行性都是抢先的。有趣的是,尽管如此,该语言并没有为锁定提供真正的支持。相反,通道通信通常提供足够的同步,并鼓励程序员安排任何数据始终有一个明确的所有者。显式锁定是不必要的。

自由线程

回到 Plan 9 世界,随着 Plan 9 被移植到越来越多的体系结构,Alef 编译器被证明难以维护。Libthread 最初是为了将 Alef 程序移植到 C 语言而创建的,这样 Alef 编译器就可以退役了。Alef 的 procs 和 tasks 在 libthread 中称为 procs 和 threads。手册页 是权威参考 。

Go

Rob Pike 和 Ken Thompson 转向 Google,并将 CSP 置于Go 语言并发支持的中心。

入门

要了解模型,尤其是进程和线程如何交互,值得阅读 Alef 用户指南 [8]。本演示文稿的前 30 张幻灯片 很好地介绍了 Alef 构造如何在 C 中表示。

CSP 模型威力的最佳例子是 McIlroy 和 Pike 的论文,如上所述 [10] [11]。

Rob Pike 的主页包含有关并发编程的课程的讲义: 介绍和幻灯片关于上述两篇论文: 斜视 和 窗口系统。三者中的最后一个提供了一个很好的例子,说明了 Plan 9 程序通常如何使用过程和任务。

Rob Pike 在 Google 进行了一次技术演讲 ,提供了很好的介绍(57 分钟视频)。

Rob Pike与 Russ Cox 的 2010 年 Google I/O 谈话 的一半 展示了如何使用通道和 Go 的并发性来实现负载平衡工作管理系统。

相关资源

John Reppy将相同的想法应用于 ML,产生了Concurrent ML。他使用 CML 构建了eXene多线程(非事件驱动)X Window System 工具包等。

参考
[1] C. A. R. Hoare, “Communicating Sequential Processes,” Communications of the ACM 21(8) (August 1978), 666-677.

[1a]C. A. R. Hoare, Communicating Sequential Processes. Prentice Hall, Englewood Cliffs, New Jersey, 1985.

[2] Michael S. Mahoney, ed., The Unix Oral History Project, Release 0: The Beginning

[3] M. Douglas McIlroy, internal Bell Labs memorandum, October 1964.

[4] Luca Cardelli and Rob Pike, “Squeak: a Language for Communicating with Mice,” Computer Graphics, 19(3) (July 1985: SIGGRAPH '85 Proceedings), 199-204.

[5] Rob Pike, “The Implementation of Newsqueak,” Software–Practice and Experience, 20(7) (July 1990), 649-659.

[6] Rob Pike, “Newsqueak: a Language for Communicating with Mice,” Computing Science Technical Report 143, AT&T Bell Laboratories, Murray Hill, 1989.

[7] Phil Winterbottom, “Alef Language Reference Manual,” in Plan 9 Programmer’s Manual: Volume Two, AT&T, Murray Hill, 1995.

[8] Bob Flandrena, “Alef Users’ Guide,” in Plan 9 Programmer’s Manual: Volume Two, AT&T, Murray Hill, 1995.

[9] Dennis M. Ritchie, “The Limbo Programming Language,” in Inferno Programmer’s Manual, Volume 2, Vita Nuova Holdings Ltd., York, 2000.

[10] M. Douglas McIlroy, “Squinting at Power Series,” Software–Practice and Experience, 20(7) (July 1990), 661-683.

[11] Rob Pike, “A Concurrent Window System,” Computing Systems, 2(2) 133-153.

[12] Rob Pike, “Acme: A User Interface for Programmers,” Proceedings of the Winter 1994 USENIX Conference, 223-234.

[13] golang.org, “The Go Programming Language”.

[14] Gerard Holzmann, “Spin’s Roots”.

[15] Gerard Holzmann, “Promela Language Reference”.

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值