gpt4 book ai didi

go - 单 channel 上的 Goroutine 解锁顺序

转载 作者:IT老高 更新时间:2023-10-28 13:10:50 25 4
gpt4 key购买 nike

Goroutines 在 channel 上阻塞的顺序是否决定了它们解除阻塞的顺序?我不关心发送的消息的顺序(它们保证是有序的),但会解除阻塞的 Goroutines 的顺序。

想象一个在多个 Goroutine(1、2 和 3)之间共享的空 Channel ch,每个 Goroutine 都试图在 ch 上接收消息。由于 ch 为空,每个 Goroutine 都会阻塞。当我向 ch 发送消息时,Goroutine 1 会先解除阻塞吗?或者 2 或 3 可能会收到第一条消息? (反之亦然,Goroutines 试图发送)

我有一个 playground这似乎表明 Goroutines 阻塞的顺序是它们被解除阻塞的顺序,但我不确定这是否是由于实现而导致的未定义行为。

最佳答案

这是一个很好的问题——它涉及到并发设计时的一些重要问题。如前所述,根据当前的实现,您的具体问题的答案是基于 FIFO 的。它不太可能永远不同,除非实现者决定,比如说,后进先出法更好。

不过,无法保证。因此,您应该避免创建依赖特定实现的代码。

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

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

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

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

由于当前的 FIFO 行为,对 channel 端的共享访问很可能提供一定程度的公平性,这似乎就足够了。但是如果你想要保证它(不管实现的不确定性),可以使用 select 和数组中的点对点 channel 包。公平索引很容易实现,方法是始终按将最后选择的放在堆底部的顺序优先选择它们。此解决方案可以保证公平,但可能会带来很小的性能损失。

(旁白:参见 "Wot No Chickens" 英国坎特伯雷的研究人员发现了一个关于 Java 虚拟机的公平性缺陷的有趣发现 - 该缺陷从未得到纠正!)

关于go - 单 channel 上的 Goroutine 解锁顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25860633/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com