Cond在Locker的基础上增加的一个消息通知的功能。但是它只能按照顺序去使一个goroutine解除阻塞。
Cond有三个方法:Wait,Signal,Broadcast。
Wait添加一个计数,也就是添加一个阻塞的goroutine。
Signal解除一个goroutine的阻塞,计数减一。
Broadcast接触所有wait goroutine的阻塞。
那外部传入的Locker,是对wait,Signal,Broadcast进行保护。防止发送信号的时候,不会有新的goroutine进入wait。在wait逻辑完成前,不会有新的事件发生。
注意:在调用Signal,Broadcast之前,应确保目标进入Wait阻塞状态。
例子:
package main
import (
"fmt"
"sync"
"time"
)
func main() {
wait := sync.WaitGroup{}
locker := new(sync.Mutex)
cond := sync.NewCond(locker)
for i := 0; i < 3; i++ {
go func(i int) {
defer wait.Done()
wait.Add(1)
cond.L.Lock()
fmt.Println("Waiting start...")
cond.Wait()
fmt.Println("Waiting end...")
cond.L.Unlock()
fmt.Println("Goroutine run. Number:", i)
}(i)
}
time.Sleep(2e9)
cond.L.Lock()
cond.Signal()
cond.L.Unlock()
time.Sleep(2e9)
cond.L.Lock()
cond.Signal()
cond.L.Unlock()
time.Sleep(2e9)
cond.L.Lock()
cond.Signal()
cond.L.Unlock()
wait.Wait()
}
输出:
Waiting start... Waiting start... Waiting start... Waiting end... Goroutine run. Number: 0 Waiting end... Goroutine run. Number: 1 Waiting end... Goroutine run. Number: 2
可以看出来,每执行一次Signal就会执行一个goroutine。如果想让所有的goroutine执行,那么将所有的Signal换成一个Broadcast方法可以。