Golang 与 Hoare 的 CSP-Language 的主要区别

看看来自 Tony Hoare 1978 年开创性论文中的例子的声明:

Go 的设计深受 Hoare 论文的影响。尽管 Go 与论文中使用的示例语言有很大不同,但这些示例仍然很容易翻译。除了语法之外,最大的区别是 Go 将并发通信的管道明确建模为通道,而 Hoare 语言的进程直接向彼此发送消息,类似于 Erlang。Hoare 在第 7.3 节中暗示了这种可能性,但有“每个端口都恰好连接到另一个进程中的另一个端口”的限制,在这种情况下,这将是一个主要的语法差异。

我糊涂了。

Hoare 语言中的进程直接相互通信。Go 例程也直接相互通信,但使用通道。

那么在golang中有什么影响有限制。真正的区别是什么?


潇湘沐
浏览 244回答 3
3回答

慕村225694

答案需要更全面地了解 Hoare 在 CSP 方面的工作。他的工作进展可以概括为三个阶段:基于 Dijkstra 的信号量,Hoare 开发了监视器。这些在 Java 中使用,除了 Java 的实现包含一个错误(参见 Welch 的文章Wot No Chickens)。不幸的是,Java 忽略了 Hoare 的后期工作。CSP由此而生。最初,CSP 需要从进程 A 到进程 B 的直接交换。这种集合方法被 Ada 和 Erlang 使用。CSP 于 1985 年完成,当时他的书首次出版。CSP 的最终版本包括 Go 中使用的通道。David May 与牛津大学的 Hoare 团队一起开发了Occam,这是一种有意将 CSP 融入实用编程语言的语言。CSP 和 Occam 相互影响(例如在The Laws of Occam Programming 中)。多年来,Occam 只在 Transputer 处理器上可用,它的架构适合 CSP。最近,Occam 已针对其他处理器进行开发,并且还吸收了 Pi 演算以及其他通用同步原语。因此,要回答最初的问题,将 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 相关。但它们是相关的,因为它们直接涉及安全并发编码。

长风秋雁

这正是重点:在 Hoare 的初始论文(以及 Erlang)中使用的示例语言中,进程 A 直接与进程 B 对话,而在 Go 中,goroutine A 与通道 C 对话,goroutine B 在 Go the channels 中监听通道 CIe是显式的,而在 Hoare 的语言和 Erlang 中,它们是隐式的。

凤凰求蛊

最近,我一直在深入研究 Go 的通道,并且在并发和并行方面工作了很多年,尽管我永远无法自称了解这方面的一切。我认为您要问的是向频道发送消息和直接向彼此发送消息之间的细微区别是什么?如果我理解你,快速回答很简单。发送到通道为通道两侧的并行/并发提供了机会。美观,可扩展。我们生活在一个并发的世界。从 A 向 B 发送一长串连续的消息(异步)意味着 B 需要以与 A 发送消息几乎相同的速度处理消息,除非有多个 B 实例有机会处理从通道,从而分担工作量。关于通道的好处是你可以有许多生产者/接收者 go-routines,它们能够将消息推送到队列,或者从队列中消费并相应地处理它。如果你线性地思考,就像一个单核 CPU,并发基本上就像有一百万个工作要做。知道单核 CPU 一次只能做一件事,但同时也看到它给人的错觉是很多事情同时发生。在执行某些代码时,操作系统需要等待一段时间才能从网络、磁盘、键盘、鼠标等返回某些内容,甚至某些进程会休眠一段时间,这给操作系统提供了做其他事情的机会同时。这一切都发生得非常快,造成了并行的错觉。另一方面,并行性是不同的,因为该作业可以在完全不同的 CPU 上运行,独立于其他 CPU 的运行情况,因此不会在与其他 CPU 相同的约束下运行(尽管大多数操作系统都做得很好)在确保工作负载均匀分布以在其所有 CPU 上运行时 - 也许 CPU 饥渴、不合作的非操作系统生成代码除外,但即使如此,操作系统也会驯服它们。关键是,拥有多核 CPU 意味着更多的并行性和更多的并发性可以发生。想象一下银行里的一个队列,它扇出到许多可以帮助你的柜员。如果没有任何出纳员为任何客户提供服务,则一名出纳员选择处理下一个客户并变得忙碌,直到他们都变得忙碌为止。每当客户离开柜员时,该柜员就能够处理队列中的下一位客户。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go