本身不是锁,但是经常和锁结合使用
使用流程:
创建 条件变量:var cond sync.Cond
指定条件变量用的 锁: cond.L = new(sync.Mutex)
cond.L.Lock() 给公共区加锁(互斥量)
判断是否到达 阻塞条件(缓冲区满/空) —— for 循环判断
for len(ch) == cap(ch) { cond.Wait() }—— 1) 阻塞 2) 解锁 3) 加锁
访问公共区 —— 读、写数据、打印
解锁条件变量用的 锁 cond.L.Unlock()
唤醒阻塞在条件变量上的 对端。 signal() Broadcast()
package main
import (
"fmt"
"math/rand"
"time"
"sync"
)
var cond sync.Cond
func producer(out chan <- int,idx int) {
for {
cond.L.Lock() // 条件变量对应互斥锁加锁
for len(out) == 3 { // 产品区满,等待消费者消费
cond.Wait() // 挂起当前go程,等待条件变量满足,被消费者唤醒
}
num := rand.Intn(1000)
out <- num
fmt.Printf("%dth 生产者 产生数据 %3d, 公共区 剩余%d个数据\n",idx,num,len(out));
cond.L.Unlock()
cond.Signal() //唤醒阻塞的消费者
time.Sleep(time.Second)
}
}
func consumer(in <- chan int,idx int) {
for {
cond.L.Lock()
for len(in) == 0 {
cond.Wait()
}
num := <- in
fmt.Printf("%dth 消费者 消费数据 %3d, 公共区 剩余%d个数据\n",idx,num,len(in));
cond.L.Unlock()
cond.Signal() //唤醒阻塞的生产者
time.Sleep(time.Millisecond * 500)
}
}
func main() {
rand.Seed(time.Now().UnixNano())
quit := make(chan bool)
product := make(chan int,3)
cond.L = new(sync.Mutex)
for i := 0;i < 5;i++ {
go producer(product,i+1)
}
for i := 0;i < 3;i++ {
go consumer(product,i+1)
}
<-quit
}