一、条件变量Cond的定义
- Go语言里的条件变量,是一个结构体,它包括对应的方法和属性字段。
- Cond实现了⼀个条件变量,⼀个线程集合地,供线程等待或者宣布某事件的发⽣。
- 每个Cond实例都有⼀个相关的锁(⼀般是*Mutex或 *RWMutex类型的值),它必须在改变条件时或者调⽤Wait⽅法时保持锁定。 Cond可以创建为其他结构体的字段, Cond在开始使⽤后不能被拷⻉。 条件变量:sync.Cond,多个goroutine等待或接受通知的集合地。
- 原型
type Cond struct {
noCopy noCopy
L Lock
notify notifyList
checker copyChecker
}
二、Cond里的方法
- func NewCond(l Locker) *Cond
使⽤锁 I 创建一个 *Cond。 Cond条件变量,总是要和锁结合使用。 - func (c *Cond) Broadcast()
Broadcast唤醒所有等待c的线程。调⽤者在调⽤本⽅法时,建议(但并⾮必须)保持c.L的锁定。 - func (c *Cond) Signal()
Signal唤醒等待c的⼀个线程(如果存在)。调⽤者在调⽤本⽅法时,建议(但并⾮必须)保持c.L的锁定。 发送通知给⼀个⼈。 - func (c *Cond) Wait()
a) Wait⾃⾏解锁c.L并阻塞当前线程,在之后线程恢复执⾏时, Wait⽅法会在返回前锁定c.L。和其他系统不同, Wait除⾮被Broadcast或者Signal唤醒,不会主动返回。 ⼴播给所有⼈。
b) 因为线程中Wait⽅法是第⼀个恢复执⾏的,⽽此时c.L未加锁。调⽤者不应假设Wait恢复时条件已满⾜,相反,调⽤者应在循环中等待。
案例1. 条件变量的使用
//myCondDes.go
// myCondDes project main.go
package main
import (
"fmt"
"sync"
"time"
)
func main() {
var mutex sync.Mutex
cond := sync.Cond{L: &mutex}
condition := false
go func() {
time.Sleep(1 * time.Second)
cond.L.Lock()
fmt.Println("子goroutine已经锁定...")
fmt.Println("子goroutine更改条件数值,并发送通知...")
condition = true //更改数值
cond.Signal() //发送通知:一个goroutine
fmt.Println("子goroutine...继续...")
time.Sleep(5 * time.Second)
fmt.Println("子goroutine已经解锁!")
cond.L.Unlock()
}()
cond.L.Lock()
fmt.Println("main 已经锁定...")
if !condition {
fmt.Println("main 即将等待...")
//1.wait尝试解锁
//2.等待-->当前的goroutine进入阻塞状态,等待被唤醒: signal(), broadcast()
//3.一旦被唤醒后,又被锁定
cond.Wait()
fmt.Println("main 被唤醒...")
}
fmt.Println("main 继续")
fmt.Println("main 解锁...")
cond.L.Unlock()
time.Sleep(3 * time.Second)
}
效果如下: