答案需要更全面地了解 Hoare 在 CSP 方面的工作。他的工作进展可以概括为三个阶段:
因此,要回答最初的问题,将 Go 与 CSP 和 Occam 进行比较可能会有所帮助。
通道:CSP、Go 和 Occam 都具有相同的通道语义。此外,Go 可以轻松地将缓冲添加到通道中(Occam 没有)。
选择:CSP 定义了内部和外部选择。但是,Go 和 Occam 都有一种选择:在 Go 中选择,在 Occam 中选择ALT。事实证明,有两种 CSP 选择在实际语言中不太重要。
Occam 的ALT允许条件保护,但 Go 的select不允许(有一个解决方法:可以将通道别名设置为nil以模仿相同的行为)。
移动性:Go 允许通过通道发送通道端(连同其他数据)。这创建了一个动态变化的拓扑结构,超出了 CSP 中的可能性,但 Milner 的 Pi 演算(从他的 CCS 中)被开发来描述这样的网络。
进程:goroutine 是一个分叉的进程;它在它想要的时候终止并且它没有父级。这不像 CSP / Occam,其中的过程是组合式的。
一个例子在这里会有所帮助:首先是奥卡姆(nb 缩进很重要)
SEQ
PAR
processA()
processB()
processC()
其次去
go processA()
go processB()
processC()
在 Occam 案例中,processC 直到 processA 和 processB 都终止后才会启动。在 Go 中,processA 和 processB 很快分叉,然后 processC 直接运行。
共享数据:CSP 并不真正直接关注数据。但有趣的是,Go 和 Occam 在共享数据方面存在重要差异。当多个 goroutine 共享一组公共数据变量时,可能出现竞争条件;Go 出色的竞态检测器有助于消除问题。但 Occam 采取不同的立场:在编译时阻止共享可变数据。
别名:与上述相关,Go 允许多个指针指向每个数据项。Occam 中不允许使用此类别名,从而减少检测竞争条件所需的工作量。
后两点与 Hoare 的 CSP 相关,而更多地与 May 的 Occam 相关。但它们是相关的,因为它们直接涉及安全并发编码。