条件变量结构体
Cond
先看一下Cond的源码
type Cond struct {
noCopy noCopy
// L is held while observing or changing the condition
L Locker // 在条件变量中有把锁
notify notifyList
checker copyChecker
}
条件变量结构体中有一把锁
所以条件变量就可以有加锁和解锁的功能
再说一下条件变量Cond的方法
方法一:func (c *Cond) Wait():
方法二:func (c *Cond) Signal():唤醒一个人
方法三:func (c *Cond) Broadcast():唤醒所有的人(惊群)
wait的功能有三个
1、阻塞
2、解锁
3、加锁
说一下方法的具体细节
1.wait一旦阻塞,就不会自动去抢锁
需要被唤醒后才能去抢锁
wait需要被signal或者broadcast唤醒
wait解锁并且阻塞当前的线程
需要调用broadcast或者signal唤醒后
线程才恢复执行
不会主动醒过来
2.signal唤醒等待c的一个线程
在调用这个方法的时候,建议是保持c.L的锁定
单发通知: 给一个wait的线程发送通知
3.broadcast唤醒所有wait的线程,建议保持锁定
广播通知: 给所有wait的线程发送通知
我们来一个例子
var cond sync.Cond //条件变量
//生产者
func producer(in chan<- int){
for {
cond.L.Lock()
for len(in)==3{
cond.Signal()
cond.Wait() //阻塞——解锁——加锁
}
num:=rand.Intn(100)
fmt.Println("生产了",num)
in<-num
//cond.Broadcast() //惊群
cond.L.Unlock()
}
}
//消费者
func consumer(out <-chan int ) {
for {
cond.L.Lock()
for len(out)==0{
cond.Signal()
cond.Wait() //阻塞——解锁——加锁
}
num:=<-out
fmt.Println("消费了:",num)
//cond.Broadcast() //惊群
cond.L.Unlock()
}
}
func main() {
rand.Seed(time.Now().UnixNano()) //随机种子
cond.L=new(sync.Mutex) //条件变量中的锁
c:=make(chan int,3) //缓冲区
for i:=1;i<=5 ;i++ { //5个协程并发生产
go producer(c)
}
for i:=1;i<=5 ;i++ { //5个协程并发消费
go consumer(c)
}
select {
}
}