Concurrency 并发Go例程的相互执行问题

Concurrency 并发Go例程的相互执行问题,concurrency,go,concurrent-programming,goroutine,Concurrency,Go,Concurrent Programming,Goroutine,在我的代码中有三个并发例程。我试着简要介绍一下我的代码 Routine 1 { do something *Send int to Routine 2 Send int to Routine 3 Print Something Print Something* do something } Routine 2 { do something *Send int to Routine 1 Send int to Routine 3 Print Something Print Somethin

在我的代码中有三个并发例程。我试着简要介绍一下我的代码

Routine 1 {
do something

*Send int to Routine 2
Send int to Routine 3
Print Something
Print Something*

do something
}

Routine 2 {
do something

*Send int to Routine 1
Send int to Routine 3
Print Something
Print Something*

do something
}

Routine 3 {
do something

*Send int to Routine 1
Send int to Routine 2
Print Something
Print Something*

do something
}

main {
routine1
routine2
routine3
}
我希望,当两个do之间的代码(两个星号之间的代码)正在执行时,控制流不能转到其他go例程。例如,当routine1执行双星之间的事件(发送和打印事件)时,例程2和3必须被阻止(意味着执行流不会从例程1传递到例程2或例程3)。完成最后一个打印事件后,执行流可能会传递到例程2或例程3。有人能帮我指定,我如何实现这一点吗?WaitGroup是否可以实现上述规范?有谁能给我一个简单的例子来说明如何使用WaitGroup实现上面指定的例子吗。谢谢

注:可能这是重复的问题。我尝试使用同步锁机制,但是,可能是因为我有一个大的代码,这就是为什么我不能把锁解锁正确,它创造了死锁的情况(或可能是我的是)。谁能帮我一个简单的程序,这样我就可以做到这一点我给出了一个简单的代码示例,在这里,我想在互斥锁(对于例程1)中放置两个打印并发送事件,因此例程2不能中断它。你能告诉我怎么可能吗。给出了一种可能的解决方案,
这会产生错误。

为什么要这样做

死锁问题是,如果不允许调度其他goroutine,那么通道发送将无法继续,除非存在缓冲。Go的通道有有限的缓冲,所以在它们满时被发送之前,您最终会遇到耗尽的竞争条件。您可以引入无限缓冲,或者将每个发送放在它自己的goroutine中,但它再次归结为:为什么要这样做;你想达到什么目标


另一件事:如果您只想确保*s之间的三组代码互斥,那么可以使用互斥。如果要确保没有代码中断块,无论它挂起在何处,则可能需要使用runtime.LockOSThread和runtime.UnlockOSThread。这些都是相当低的水平,你需要知道你在做什么,他们很少需要。如果您希望没有其他goroutine在运行,则必须有runtime.GOMAXPROCS(1),这是当前的默认值

你为什么要这样做

死锁问题是,如果不允许调度其他goroutine,那么通道发送将无法继续,除非存在缓冲。Go的通道有有限的缓冲,所以在它们满时被发送之前,您最终会遇到耗尽的竞争条件。您可以引入无限缓冲,或者将每个发送放在它自己的goroutine中,但它再次归结为:为什么要这样做;你想达到什么目标


另一件事:如果您只想确保*s之间的三组代码互斥,那么可以使用互斥。如果要确保没有代码中断块,无论它挂起在何处,则可能需要使用runtime.LockOSThread和runtime.UnlockOSThread。这些都是相当低的水平,你需要知道你在做什么,他们很少需要。如果您希望没有其他goroutine在运行,则必须有runtime.GOMAXPROCS(1),这是当前的默认值

回答你的问题的问题是,似乎没有人理解你真正的问题是什么。我看到你反复询问大致相同的问题,尽管没有取得任何进展。这样说没有冒犯之意。这是一种尝试,通过一个建议来帮助你,以一种他人可以理解的方式重新阐述你的问题。作为一个可能的好的副作用,一些问题确实可以自己解决,同时以一种可以理解的方式向其他人解释。我自己也经历过很多次

另一个暗示可能是显式同步和通道通信的可疑组合。这并不意味着设计一定会被打破。这在典型/简单的情况下是不会发生的。同样,您的问题可能是非典型的/非琐碎的

也许仅仅使用渠道就可以重新设计您的问题。实际上,我相信所有涉及显式同步(in-Go)的问题都可以在只使用通道的情况下进行编码。也就是说,确实有些问题很容易用显式同步编写。此外,信道通信虽然便宜,但不像大多数同步原语那样便宜。但这可以在以后代码运行时处理。如果有人说sync.Mutex的“模式”会明显出现在代码中,那么应该可以切换到sync.Mutex,并且当代码已经运行并且希望在进行调整时有测试来观察您的步骤时,这样做会容易得多

试着把你的goroutines想象成独立的代理:

  • 独家拥有从通道接收的数据。语言会 如果不强制执行,则必须部署自己的规程
  • 不要再触摸他们发送到频道的数据。它遵循第一条规则,但非常重要,必须明确
  • 通过数据类型与其他代理(goroutine)交互,这些数据类型封装了整个工作流/计算单元。这消除了您之前在“单元”完成之前获取正确数量通道消息的困难
  • 对于他们使用的每个通道,在之前必须绝对清楚通道是否必须无缓冲,是否必须为固定数量的项目进行缓冲,或者是否可以解除绑定
  • 不必考虑(知道)其他代理正在做什么,只要从他们那里得到一条消息,如果代理需要完成自己的任务——这是全局的一部分
即使使用如此少的经验法则,也有望产生更容易推理的代码,并且通常不需要任何其他同步。)我在