一尘不染

单通道Goroutine解锁的顺序

go

Goroutines在通道上的阻塞顺序是否决定了它们将解除阻塞的顺序?我不关心所发送消息的顺序(它们一定会被排序),但是不会影响Goroutines的顺序。

想象一下ch在多个Goroutine(1、2和3)之间共享一个空通道,每个Goroutine都尝试在上接收消息ch。由于ch为空,每个Goroutine将阻塞。当我向发送消息时ch,Goroutine
1将首先解锁吗?还是2或3可能会收到第一条消息?(反之亦然,Goroutine尝试发送)

我有一个游乐场,似乎在暗示Goroutines阻塞的顺序是它们被解除阻塞的顺序,但是由于实现的原因,我不确定这是否是未定义的行为。


阅读 175

收藏
2020-07-02

共1个答案

一尘不染

这是一个好问题-
在进行并行设计时涉及一些重要问题。如前所述,根据当前的实现,针对特定问题的答案是基于FIFO的。除非是实施者出于某种原因而决定,例如,LIFO更好,否则它不可能再有所不同。

没有保证 ,虽然。因此,您应该避免创建 依赖 于特定实现的代码。

更为广泛的问题涉及 不确定性公平饥饿

也许令人惊讶的是,基于CSP的系统 中的不 确定性 并非 来自并行发生的事情。这是 可能的 ,因为并发性的,而不是 因为 并发。相反,
做出选择时会出现不确定性
。在CSP的形式代数中,这是数学建模的。幸运的是,您不需要知道数学就能使用Go。但是从形式上讲,两个goroutines代码并行执行,并且如果消除了所有选择,结果仍然可以确定。

Go允许select通过goroutine之间共享的通道的末端显式地或隐式地引入非确定性的选择。如果您具有点对点(一位读者,一位作家)的渠道,则不会出现第二种渠道。因此,如果在特定情况下很重要,则可以选择设计方案。

公平饥饿
通常是同一枚硬币的相反面。饥饿是那些动态问题(以及死锁,活锁和比赛条件)之一,可能导致性能下降,更可能导致错误的行为。这些动态问题是无法测试的(对此有更多了解),需要进行一些层次分析才能解决。显然,如果系统的一部分由于无法访问某些资源而无法响应,那么在管理这些资源时就需要更大的公平性。

由于当前的FIFO行为,对通道端的共享访问可能会提供一定程度的公平性,这似乎足够了。但是,如果您希望得到保证(无论实现不确定性如何),则可以select在数组中使用和一包点对点通道。通过始终按优先顺序选择优先顺序,将最后选择的顺序放在桩的底部,可以轻松实现公平索引。该解决方案可以
保证 公平,但可能会降低性能。

(此外:
英国坎特伯雷的研究人员就Java虚拟机的公平性漏洞进行了一项颇为有趣的发现,请参阅“无鸡不育”,该问题从未得到纠正!)

2020-07-02