并发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 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

}

我希望在执行两个代码之间的某些操作(两个星号之间的代码)时,控制流一定不能进入其他goroutine。例如,当例程1正在执行两颗星之间的事件(发送和打印事件)时,例程2和3必须被阻止(执行的平均流量不会从例程1传递到例程2或3)。在完成上一个打印事件后,执行流程可能会传递到例程2或3。有人可以通过指定帮助我的方式,我该如何实现呢?是否可以通过WaitGroup来实现上述规范?任何人都可以通过举一个简单的示例向我展示如何使用WaitGroup来实现上面指定的示例。谢谢。


注意:我提供两个发送和两个打印选项,实际上有很多发送和打印功能。


子衿沉夜
浏览 210回答 3
3回答

潇湘沐

如果我正确理解了它,那么您想要的是防止同时执行每个功能的某些部分和其他功能。下面的代码可以做到这一点:fmt.Println当其他例程正在运行时,行不会发生。这是发生的情况:当执行到达打印部分时,它将等待直到其他例程结束(如果它们正在运行),并且在执行此打印行时,其他例程不会启动并等待。我希望这就是您想要的。如果我对此有误,请纠正我。package mainimport (&nbsp; &nbsp; "fmt"&nbsp; &nbsp; "rand"&nbsp; &nbsp; "sync")var (&nbsp; &nbsp; mutex1, mutex2, mutex3 sync.Mutex&nbsp; &nbsp; wg sync.WaitGroup)func Routine1() {&nbsp; &nbsp; mutex1.Lock()&nbsp; &nbsp; // do something&nbsp; &nbsp; for i := 0; i < 200; i++ {&nbsp; &nbsp; &nbsp; &nbsp; mutex2.Lock()&nbsp; &nbsp; &nbsp; &nbsp; mutex3.Lock()&nbsp; &nbsp; &nbsp; &nbsp; fmt.Println("value of z")&nbsp; &nbsp; &nbsp; &nbsp; mutex2.Unlock()&nbsp; &nbsp; &nbsp; &nbsp; mutex3.Unlock()&nbsp; &nbsp; }&nbsp; &nbsp; // do something&nbsp; &nbsp; mutex1.Unlock()&nbsp; &nbsp; wg.Done()}func Routine2() {&nbsp; &nbsp; mutex2.Lock()&nbsp; &nbsp; // do something&nbsp; &nbsp; for i := 0; i < 200; i++ {&nbsp; &nbsp; &nbsp; &nbsp; mutex1.Lock()&nbsp; &nbsp; &nbsp; &nbsp; mutex3.Lock()&nbsp; &nbsp; &nbsp; &nbsp; fmt.Println("value of z")&nbsp; &nbsp; &nbsp; &nbsp; mutex1.Unlock()&nbsp; &nbsp; &nbsp; &nbsp; mutex3.Unlock()&nbsp; &nbsp; }&nbsp; &nbsp; // do something&nbsp; &nbsp; mutex2.Unlock()&nbsp; &nbsp; wg.Done()}func Routine3() {&nbsp; &nbsp; mutex3.Lock()&nbsp; &nbsp; // do something&nbsp; &nbsp; for i := 0; i < 200; i++ {&nbsp; &nbsp; &nbsp; &nbsp; mutex1.Lock()&nbsp; &nbsp; &nbsp; &nbsp; mutex2.Lock()&nbsp; &nbsp; &nbsp; &nbsp; fmt.Println("value of z")&nbsp; &nbsp; &nbsp; &nbsp; mutex1.Unlock()&nbsp; &nbsp; &nbsp; &nbsp; mutex2.Unlock()&nbsp; &nbsp; }&nbsp; &nbsp; // do something&nbsp; &nbsp; mutex3.Unlock()&nbsp; &nbsp; wg.Done()}func main() {&nbsp; &nbsp; wg.Add(3)&nbsp; &nbsp; go Routine1()&nbsp; &nbsp; go Routine2()&nbsp; &nbsp; Routine3()&nbsp; &nbsp; wg.Wait()}更新:让我在这里解释这三个互斥锁:一个互斥锁,如文档所述:“互斥锁”。这意味着当您调用Lock互斥锁时,如果其他人已锁定相同的互斥锁,则代码仅在此处等待。在您致电之后Unlock,被阻止的代码将立即恢复。在这里,我通过在函数的开头锁定互斥锁并将其解锁来将每个函数置于其自己的互斥锁中。通过这种简单的机制,您可以避免与这些功能同时运行所需的任何代码部分。例如,在您想要拥有运行时不应该运行的代码的任何地方Routine1,只需mutex1在该代码的开头锁定并在最后解锁即可。这就是我在Routine2和中的适当行中所做的事情Routine3。希望能澄清一些事情。

一只甜甜圈

另一种方法是拥有一个控制通道,在任何时候只允许执行一个goroutine,并且每当它们完成其原子操作时,每个例程就会发回“ control lock”:package mainimport "fmt"import "time"func routine(id int, control chan struct{}){&nbsp; &nbsp; for {&nbsp; &nbsp; &nbsp; &nbsp; // Get the control&nbsp; &nbsp; &nbsp; &nbsp; <-control&nbsp; &nbsp; &nbsp; &nbsp; fmt.Printf("routine %d got control\n", id)&nbsp; &nbsp; &nbsp; &nbsp; fmt.Printf("A lot of things happen here...")&nbsp; &nbsp; &nbsp; &nbsp; time.Sleep(1)&nbsp; &nbsp; &nbsp; &nbsp; fmt.Printf("... but only in routine %d !\n", id)&nbsp; &nbsp; &nbsp; &nbsp; fmt.Printf("routine %d gives back control\n", id)&nbsp; &nbsp; &nbsp; &nbsp; // Sending back the control to whichever other routine catches it&nbsp; &nbsp; &nbsp; &nbsp; control<-struct{}{}&nbsp; &nbsp; }}func main() {&nbsp; &nbsp; // Control channel is blocking&nbsp; &nbsp; control := make(chan struct{})&nbsp; &nbsp; // Start all routines&nbsp; &nbsp; go routine(0, control)&nbsp; &nbsp; go routine(1, control)&nbsp; &nbsp; go routine(2, control)&nbsp; &nbsp; // Sending control to whichever catches it first&nbsp; &nbsp; control<-struct{}{}&nbsp; &nbsp; // Let routines play for some time...&nbsp; &nbsp; time.Sleep(10)&nbsp; &nbsp; // Getting control back and terminating&nbsp; &nbsp; <-control&nbsp; &nbsp; close(control)&nbsp; &nbsp; fmt.Println("Finished !")}打印:routine 0 got controlA lot of things happen here...... but only in routine 0 !routine 0 gives back controlroutine 1 got controlA lot of things happen here...... but only in routine 1 !routine 1 gives back controlroutine 2 got controlA lot of things happen here...... but only in routine 2 !routine 2 gives back controlroutine 0 got controlA lot of things happen here...... but only in routine 0 !routine 0 gives back controlroutine 1 got controlA lot of things happen here...... but only in routine 1 !routine 1 gives back controlroutine 2 got controlA lot of things happen here...... but only in routine 2 !routine 2 gives back controlroutine 0 got controlA lot of things happen here...... but only in routine 0 !routine 0 gives back controlroutine 1 got controlA lot of things happen here...... but only in routine 1 !routine 1 gives back controlroutine 2 got controlA lot of things happen here...... but only in routine 2 !routine 2 gives back controlroutine 0 got controlA lot of things happen here...... but only in routine 0 !routine 0 gives back controlroutine 1 got controlA lot of things happen here...... but only in routine 1 !routine 1 gives back controlroutine 2 got controlA lot of things happen here...... but only in routine 2 !routine 2 gives back controlFinished !
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go