为了账号安全,请及时绑定邮箱和手机立即绑定

单通道 Goroutine 解锁顺序

单通道 Goroutine 解锁顺序

Go
杨__羊羊 2021-08-16 18:57:34
Goroutines 在通道上阻塞的顺序是否决定了它们将解除阻塞的顺序?我不关心发送的消息的顺序(它们保证是有序的),而是将解除阻塞的 Goroutine 的顺序。想象一个ch在多个 Goroutines(1、2 和 3)之间共享的空 Channel ,每个 Goroutine 都试图在 上接收消息ch。由于ch为空,每个 Goroutine 都会阻塞。当我向 发送消息时ch,Goroutine 1 会先解除阻塞吗?或者 2 或 3 人可能会收到第一条消息?(反之亦然,Goroutines 尝试发送)我有一个操场似乎表明 Goroutines 阻塞的顺序就是它们被解除阻塞的顺序,但我不确定这是否是由于实现而导致的未定义行为。
查看完整描述

3 回答

?
三国纷争

TA贡献1804条经验 获得超7个赞

这是一个很好的问题 - 它涉及进行并发设计时的一些重要问题。如前所述,根据当前的实现,您的具体问题的答案是基于 FIFO。它不太可能有所不同,除非实施者出于某种原因认为 LIFO 更好。

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

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

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

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

公平饥饿通常是同一枚硬币的两面。饥饿是那些可能导致性能不佳,更可能导致错误行为的动态问题之一(以及死锁、活锁和竞争条件)。这些动态问题是不可测试的(更多关于这个),需要一些层次分析来解决。显然,如果系统的一部分因为无法访问某些资源而没有响应,那么在管理这些资源时就需要更加公平。

由于当前的 FIFO 行为,对通道端的共享访问可以很好地提供一定程度的公平性,这似乎就足够了。但是,如果您希望它得到保证(无论实现的不确定性如何),则可以select在数组中使用 a和一组点对点通道。通过始终按照将最后选择的放在堆底部的顺序优先选择它们,很容易实现公平索引。此解决方案可以保证公平性,但可能会带来很小的性能损失。

(旁白:请参阅“Wot No Chickens”,了解英国坎特伯雷的研究人员关于 Java 虚拟机中的公平性缺陷的一个有点有趣的发现——该缺陷从未得到纠正!)


查看完整回答
反对 回复 2021-08-16
?
大话西游666

TA贡献1817条经验 获得超14个赞

顺序未指定,但当前的实现使用 FIFO 队列来等待 goroutine。

权威文档是Go Memory Model。内存模型没有为发送到同一个通道的两个 goroutine 定义发生在之前的关系,因此没有指定顺序。同上接收。


查看完整回答
反对 回复 2021-08-16
  • 3 回答
  • 0 关注
  • 198 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信