当前位置: 首页 > 面试题库 >

单通道Goroutine解锁的顺序

左丘繁
2023-03-14
问题内容

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

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

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


问题答案:

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

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

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

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

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

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

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

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



 类似资料:
  • 我是新来的,想知道一些很基本的问题,我不能弄清楚。 为了发挥作用(对实际需要的抽象),我需要: 用常数固定的元素初始化字符串片断 遍历此切片并为每个元素运行一个goroutine 每个goroutine将花费一定的时间来处理元素(随机秒持续时间) 作业完成后,我希望goroutine将结果推送到一个通道 然后我需要捕获来自这个通道的所有结果(在一个从主goroutine调用的函数中),将它们附加到

  • 问题内容: 我最近开始学习Go语言,但是遇到了问题。我有一个简单的go例程,该例程可以将值返回或将值推入通道。我的主要fn代表一直在执行此例程,直到满足条件或数据用尽为止。这段代码似乎在“找到”频道上陷入僵局。我究竟做错了什么? 有多名工人 可以同时在多个工人中找到物品 一旦找到物品,所有工人应停止。 。 问题答案: 一种可能的解决方案是避免使用select语句,并为接收者(或发送者,或两者)使用

  • 问题内容: 我是新手。当我注释掉第二个goroutine时,出现致命错误。我不明白是什么原因导致此错误发生。你能跟我解释一下吗? 这将输出以下代码: 问题答案: 从发送goroutine接收到所有值之后,receive的for循环块将在接收时被阻塞。运行时检测到程序被卡住并出现紧急情况。 解决方法是在发送所有值后关闭通道: 在闭路接收产生值。for循环的接收会中断false值。 从程序末尾删除。

  • 出于性能考虑的建议: 实践经验表明,如果你使用并行运算获得高于串行运算的效率:在协程内部已经完成的大部分工作,其开销比创建协程和协程间通信还高。 1 出于性能考虑建议使用带缓存的通道: 使用带缓存的通道可以很轻易成倍提高它的吞吐量,某些场景其性能可以提高至10倍甚至更多。通过调整通道的容量,甚至可以尝试着更进一步的优化其性能。 2 限制一个通道的数据数量并将它们封装成一个数组: 如果使用通道传递大

  • 作为一门 21 世纪的语言,Go 原生支持应用之间的通信(网络,客户端和服务端,分布式计算,参见第 15 章)和程序的并发。程序可以在不同的处理器和计算机上同时执行不同的代码段。Go 语言为构建并发程序的基本代码块是 协程 (goroutine) 与通道 (channel)。他们需要语言,编译器,和runtime的支持。Go 语言提供的垃圾回收器对并发编程至关重要。 不要通过共享内存来通信,而通过

  • 问题内容: 我需要使用单个任务队列和单个结果队列来启动许多工作程序。每个工人都应该以不同的goroutine开始。我需要等到所有工作人员都将完成并且任务队列将为空后再退出程序。我已经准备了goroutine同步的小例子。主要思想是我们将排队的任务计数,并等待所有工人完成工作。但是当前的实现有时会遗漏值。为什么会发生这种情况以及如何解决问题?示例代码: 问题答案: 使用sync.WaitGroup等