本文介绍了Goroutine在单通道上解封的顺序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
我不关心发送的消息的顺序(它们保证是有序的),但Goroutines的顺序会解除阻止。
设想一个空的Channel ch
在多个Goroutines(1,2和3)之间共享,每个Goroutine试图接收 ch
。由于 ch
为空,每个Goroutine都会被阻塞。当我向 ch
发送消息时,Goroutine 1会先解锁吗?或者2或3可能会收到第一条消息? (反之亦然,Goroutines试图发送)
我有一个似乎暗示着Goroutines阻止的顺序是它们被解锁的顺序,但我不确定这是否是由于实现而导致的未定义行为。解决方案
这是一个很好的问题 - 它在并发设计时遇到了一些重要的问题。如前所述,根据目前的实施情况,针对您的具体问题的答案是基于FIFO。这不可能有任何不同,除非实施者决定,例如说LIFO由于某种原因而更好。
有不能保证 ,但是。所以你应该避免在特定的实现中创建依赖的代码。
更广泛的问题涉及非确定性, 公平和饥饿。
也许令人惊讶的是,基于CSP的系统中的非确定性不来自并行发生的事情。它是可能的,因为并发性,但不是因为的并发性。相反,非决定性会在做出选择时出现。在CSP的形式代数中,这是以数学方式建模的。幸运的是,你不需要知道数学就可以使用Go。但是在形式上,两个goroutine代码并行执行,并且结果仍然可以是确定性的,只要所有的选择都被消除。Go允许通过显式引入非确定性的选择, code> select 并隐式地通过goroutines之间共享的通道的结束。如果你有点对点(一个读者,一个作者)渠道,第二类不会出现。因此,如果在特定情况下很重要,您可以选择设计方案。
通常是同一枚硬币的两侧。饥饿是这些动态问题之一(伴随着僵局,活锁和竞争条件),可能导致表现不佳,更可能出现错误的行为。这些动态问题是无法测试的(),并且需要一些关卡分析解决。显然,如果系统的一部分由于缺乏对特定资源的访问而无响应,那么就需要更加公平地管理这些资源。
共享访问权限由于当前的FIFO行为,通道末端可能会提供一定程度的公平性,这似乎足够了。但是,如果你想保证它(不管实现的不确定性如何),可以改为在数组中使用 select
和一系列点对点通道。公平索引很容易实现,总是选择最后选择的顺序排列在最下面。这个解决方案可以保证公正性,但可能会带来一些小的性能损失。
(另请参见,因为坎特伯雷的研究人员做了一些有趣的发现,英国有关Java虚拟机中的公平性缺陷 - 这个问题从未被纠正过!)
Does order in which the Goroutines block on a channel determine the order they will unblock? I'm not concerned with the order of the messages that are sent (they're guaranteed to be ordered), but the order of the Goroutines that'll unblock.
Imagine a empty Channel ch
shared between multiple Goroutines (1, 2, and 3), with each Goroutine trying to receive a message on ch
. Since ch
is empty, each Goroutine will block. When I send a message to ch
, will Goroutine 1 unblock first? Or could 2 or 3 possibly receive the first message? (Or vice-versa, with the Goroutines trying to send)
I have a playground that seems to suggest that the order in which Goroutines block is the order in which they are unblocked, but I'm not sure if this is an undefined behavior because of the implementation.
解决方案
This is a good question - it touches on some important issues when doing concurrent design. As has already been stated, the answer to your specific question is, according to the current implementation, FIFO based. It's unlikely ever to be different, except perhaps if the implementers decided, say, a LIFO was better for some reason.
There is no guarantee, though. So you should avoid creating code that relies on a particular implementation.
The broader question concerns non-determinism, fairness and starvation.
Perhaps surprisingly, non-determinism in a CSP-based system does not come from things happening in parallel. It is possible because of concurrency, but not because of concurrency. Instead, non-determinism arises when a choice is made. In the formal algebra of CSP, this is modelled mathematically. Fortunately, you don't need to know the maths to be able to use Go. But formally, two goroutines code execute in parallel and the outcome could still be deterministic, provided all the choices are eliminated.
Go allows choices that introduce non-determinism explicitly via select
and implicitly via ends of channels being shared between goroutines. If you have point-to-point (one reader, one writer) channels, the second kind does not arise. So if it's important in a particular situation, you have a design choice you can make.
Fairness and starvation are typically opposite sides of the same coin. Starvation is one of those dynamic problems (along with deadlock, livelock and race conditions) that result perhaps in poor performance, more likely in wrong behaviour. These dynamic problems are un-testable (more on this) and need some level analysis to solve. Clearly, if part of a system is unresponsive because it is starved of access to certain resources, then there is a need for greater fairness in governing those resources.
Shared access to channel ends may well provide a degree of fairness because of the current FIFO behaviour and this may appear sufficient. But if you want it guaranteed (regardless of implementation uncertainties), it is possible instead to use a select
and a bundle of point-to-point channels in an array. Fair indexing is easy to achieve by always preferring them in an order that puts the last-selected at the bottom of the pile. This solution can guarantee fairness, but probably with a small performance penalty.
(aside: see "Wot No Chickens" for a somewhat-amusing discovery made by researchers in Canterbury, UK concerning a fairness flaw in the Java Virtual Machine - which has never been rectified!)
这篇关于Goroutine在单通道上解封的顺序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!