cond是什么
- Cond实现了一种条件变量,可以使用在多个reader等待共享资源ready的场景,(如果只有一读一写,一个锁或者channel就搞定了)
- 每个Cond都会关联一个Lock(*sync.Mutex or *sync.RWMutex), 当修改条件或者调用Wait方法时,必须加锁以保护condition
- 案例:
var (
c = sync.Cond{L: &sync.Mutex{}} // 条件变量,多个reader等待共享资源ready的场景
maxNum = 15
)
func main(){
for i := 0; i < maxNum; i++{
go func(i int) {
c.L.Lock()
defer c.L.Unlock()
// Wait会释放c.L锁,并挂起调用者的goroutine,之后恢复执行
c.Wait() // Wait会在返回时对c.L加锁
// 除非被Broadcast或Signal唤醒,否则Wait不会返回
fmt.Println("goroutine:", i)
time.Sleep(time.Millisecond * 100)
}(i)
}
c.L.Lock()
maxNum = 16
c.L.Unlock()
c.Broadcast() // 广播,所有等待的goroutine都会执行
//c.Signal() // 单播,从所有等待的goroutine中随机找一个去执行
time.Sleep(time.Second * 2)
}
Broadcast和Signal的区别
- Broadcast会唤醒所有等待c的goroutine,调用Broadcast的时候,可以加锁也可以不加锁
- Signal只唤醒一个等待c的goroutine,调用Signal的时候,可以加锁也可以不加锁
Cond中Wait使用
- Wait会自动释放c.L锁,并挂起调用者的goroutine,之后恢复执行
- Wait会在返回时对c.L加锁
- 除非被Broadcast或Signal唤醒,否则Wait不会返回
- 由于Wait第一次恢复是,c.L并没有加锁,所以当Wait返回时,调用者通常不能假设条件为真
- 简单来说,只要想使用condition就必须加锁