在我的代码中有三个并发例程。我试着给我的代码一个简短的概述,
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
}
我想,而代码之间的两个做的东西(代码之间的两个星号)正在执行,控制流不能去其他go例程。例如,当routine1正在执行两个星号之间的事件(发送和打印事件)时,例程2和3必须被阻塞(意味着执行流不会从例程1传递到例程2或3)。在完成最后一个打印事件后,执行流可能会传递到例程2或3。谁能帮我说明一下,我怎么才能做到这一点?WaitGroup是否有可能实现上述规范?谁能给我一个简单的例子如何实现上述指定的例子使用WaitGroup。谢谢。
注:这可能是重复的问题。我尝试使用同步锁机制,然而,可能是因为我有一个大的代码,这就是为什么我不能正确地把锁解锁,它创建死锁的情况(或者可能是我的方法是错误产生)。有人可以帮助我通过一个简单的程序,这样我就可以做到这一点。我在这里给出了一个简单的代码示例,这里我想在互斥锁中放置两个打印并发送事件(对于例程1),因此例程2不能中断它。你能帮我一下吗?一个可能的解决方案是,http://play.golang.org/p/-uoQSqBJKS给出错误。你为什么要这样做?
死锁的问题是,如果你不允许其他例程被调度,那么你的通道发送不能继续,除非有缓冲。Go的通道有有限的缓冲,所以在它们被满的时候发送之前,你最终会遇到一个耗尽的竞争条件。你可以引入无限缓冲,或者把每个send放到自己的例程中,但这又归结为:你为什么要这样做;你想达到什么目标?
另一件事:如果你只想确保*s之间的三组代码互斥,那么是的,你可以使用互斥。如果您想确保没有代码中断您的块,无论它挂起在哪里,那么您可能需要使用运行时。LockOSThread和runtime。这些都是相当低级的,你需要知道你在做什么,很少需要它们。如果您希望没有其他运行例程,则必须使用runtime.GOMAXPROCS(1),这是当前的默认值。
回答你的问题的问题是,似乎没有人理解你的问题到底是什么。我看到你一直在问大致相同的问题,尽管没有任何进展。这样说并没有冒犯的意思。这是一种试图帮助你的建议,以一种别人可以理解的方式重新表述你的问题。作为一个可能的好的副作用,一些问题在以一种可理解的方式向他人解释时确实会自己解决。我自己已经经历过很多次了。
另一个提示可能是显式同步和通道通信的可疑混合。这并不意味着设计一定是坏的。它只是不会在典型/简单的情况下发生。再一次,你的问题可能是非典型的/不平凡的。
也许在某种程度上可以只使用通道来重新设计您的问题。实际上,我相信每个涉及显式同步(在Go中)的问题都可以在仅使用通道时进行编码。也就是说,使用显式同步编写某些问题确实非常容易。此外,通道通信虽然便宜,但不如大多数同步原语便宜。但这可以在以后的代码工作时再考虑。如果"模式"有些说同步。互斥锁将明显出现在代码中,应该可以切换到它,并且当代码已经工作并且希望有测试来观察您在进行调整时的步骤时,切换到互斥锁要容易得多。
试着把你的程序想象成独立行动的代理,
- 独占从通道接收的数据。语言将会不是强制执行,你必须部署自己的纪律。
- 不要再碰他们发送到频道的数据。它遵循第一条规则,但重要到足以明确。
- 通过数据类型与其他代理(程序)交互,它封装了整个工作流/计算单元。这消除了你之前在"单元"完成之前获得正确数量的通道消息的斗争。
- 对于他们使用的每个通道,必须在之前绝对清楚,如果通道必须未缓冲,必须为固定数量的项目缓冲,或者如果它可能未绑定。
- 如果代理需要完成自己的任务,则不必考虑(知道)其他代理在上面做什么,从它们那里获得消息-这是大局的一部分。
即使使用这么少的经验法则,也应该有希望产生更容易推理的代码,并且通常不需要任何其他同步。(我现在故意忽略关键任务应用程序的性能问题。)