在我的代码中有三个并发例程。我试着简要介绍一下我的代码,
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
}
我想要的是,当两个代码之间的代码执行时(两个星号之间的代码)正在执行,控制流不能转到其他goroutines。例如,当routine1正在执行两颗星之间的事件(发送和打印事件)时,必须阻止例程2和3(意味着执行流程不会从例程1传递到例程2或3)。完成最后一次打印事件后,执行流程可能会传递到例程2或3.任何人都可以通过指定帮助我,我该如何实现?是否可以通过WaitGroup实现上述规范?任何人都可以通过一个简单的例子向我展示如何使用WaitGroup实现上面指定的例子。感谢。
注意:我提供了两个发送和两个打印选项,实际上有很多发送和打印。
答案 0 :(得分:3)
如果我弄错了,你想要的是防止同时执行每个功能的某些部分和其他功能。以下代码执行此操作:fmt.Println
行不会在其他例程运行时发生。这是发生的事情:当执行到达打印部分时,它等待直到其他例程结束,如果它们正在运行,并且当该打印行正在执行时,其他例程不会启动并等待。我希望这就是你要找的。如果我对此错了,请纠正我。
package main
import (
"fmt"
"rand"
"sync"
)
var (
mutex1, mutex2, mutex3 sync.Mutex
wg sync.WaitGroup
)
func Routine1() {
mutex1.Lock()
// do something
for i := 0; i < 200; i++ {
mutex2.Lock()
mutex3.Lock()
fmt.Println("value of z")
mutex2.Unlock()
mutex3.Unlock()
}
// do something
mutex1.Unlock()
wg.Done()
}
func Routine2() {
mutex2.Lock()
// do something
for i := 0; i < 200; i++ {
mutex1.Lock()
mutex3.Lock()
fmt.Println("value of z")
mutex1.Unlock()
mutex3.Unlock()
}
// do something
mutex2.Unlock()
wg.Done()
}
func Routine3() {
mutex3.Lock()
// do something
for i := 0; i < 200; i++ {
mutex1.Lock()
mutex2.Lock()
fmt.Println("value of z")
mutex1.Unlock()
mutex2.Unlock()
}
// do something
mutex3.Unlock()
wg.Done()
}
func main() {
wg.Add(3)
go Routine1()
go Routine2()
Routine3()
wg.Wait()
}
更新:让我在这里解释这三个互斥锁:互斥锁是documentation says:“互斥锁定”。这意味着当您在互斥锁上调用Lock
时,如果其他人锁定了相同的互斥锁,您的代码就会等待。在您致电Unlock
之后,阻止的代码将会恢复。
这里我将每个函数放在自己的互斥锁中,方法是在函数开头锁定一个互斥锁,然后将其解锁。通过这种简单的机制,您可以避免在运行这些函数的同时运行所需的任何代码部分。例如,在Routine1
运行时,您希望拥有一个不应该运行的代码,只需在该代码的开头锁定mutex1
,最后解锁即可。这就是我在Routine2
和Routine3
中的相应行中所做的。希望澄清一切。
答案 1 :(得分:2)
您可以使用sync.Mutex
。例如,im.Lock()
和im.Unlock()
之间的所有内容都将排除其他goroutine。
package main
import (
"fmt"
"sync"
)
func f1(wg *sync.WaitGroup, im *sync.Mutex, i *int) {
for {
im.Lock()
(*i)++
fmt.Printf("Go1: %d\n", *i)
done := *i >= 10
im.Unlock()
if done {
break
}
}
wg.Done()
}
func f2(wg *sync.WaitGroup, im *sync.Mutex, i *int) {
for {
im.Lock()
(*i)++
fmt.Printf("Go2: %d\n", *i)
done := *i >= 10
im.Unlock()
if done {
break
}
}
wg.Done()
}
func main() {
var wg sync.WaitGroup
var im sync.Mutex
var i int
wg.Add(2)
go f1(&wg, &im, &i)
go f2(&wg, &im, &i)
wg.Wait()
}
答案 2 :(得分:0)
另一种方法是拥有一个控制通道,任何时候只允许执行一个goroutine,每个例程在完成原子操作时都会发送回“控制锁”:
package main
import "fmt"
import "time"
func routine(id int, control chan struct{}){
for {
// Get the control
<-control
fmt.Printf("routine %d got control\n", id)
fmt.Printf("A lot of things happen here...")
time.Sleep(1)
fmt.Printf("... but only in routine %d !\n", id)
fmt.Printf("routine %d gives back control\n", id)
// Sending back the control to whichever other routine catches it
control<-struct{}{}
}
}
func main() {
// Control channel is blocking
control := make(chan struct{})
// Start all routines
go routine(0, control)
go routine(1, control)
go routine(2, control)
// Sending control to whichever catches it first
control<-struct{}{}
// Let routines play for some time...
time.Sleep(10)
// Getting control back and terminating
<-control
close(control)
fmt.Println("Finished !")
}
打印:
routine 0 got control
A lot of things happen here...... but only in routine 0 !
routine 0 gives back control
routine 1 got control
A lot of things happen here...... but only in routine 1 !
routine 1 gives back control
routine 2 got control
A lot of things happen here...... but only in routine 2 !
routine 2 gives back control
routine 0 got control
A lot of things happen here...... but only in routine 0 !
routine 0 gives back control
routine 1 got control
A lot of things happen here...... but only in routine 1 !
routine 1 gives back control
routine 2 got control
A lot of things happen here...... but only in routine 2 !
routine 2 gives back control
routine 0 got control
A lot of things happen here...... but only in routine 0 !
routine 0 gives back control
routine 1 got control
A lot of things happen here...... but only in routine 1 !
routine 1 gives back control
routine 2 got control
A lot of things happen here...... but only in routine 2 !
routine 2 gives back control
routine 0 got control
A lot of things happen here...... but only in routine 0 !
routine 0 gives back control
routine 1 got control
A lot of things happen here...... but only in routine 1 !
routine 1 gives back control
routine 2 got control
A lot of things happen here...... but only in routine 2 !
routine 2 gives back control
Finished !
答案 3 :(得分:-2)
您是否要求显式停止其他例程的库函数?要明确一点,Go和大多数其他语言都不可能。并且同步,互斥情况不适用于您的情况。