Cond
// cond是只会执行加锁的协程,相当于加了一个标识,
// lock与ulock是标识 相当于门 ,让让正确的人(协程)进入
// wait是堵塞等待 相当于一把锁
// Signal会给信号疏通一个加锁加wait协程 相当于只能开一把锁的钥匙
// Broadcast疏通所有剩下的加锁加wait协程 相当于能够开所有加锁的钥匙万能钥匙
文章
手册:https://studygolang.com/static/pkgdoc/pkg/sync.htm#Cond
博文:https://blog.csdn.net/qq_35976351/article/details/82117769
代码示例
package main
import (
"fmt"
"sync"
"time"
)
var locker = new(sync.Mutex)
// func NewCond(l Locker) *Cond:用于创建条件,根据实际情况传入sync.Mutex或者sync.RWMutex的
指针,一定要是指针,否则会发生复制导致锁的失效
var cond = sync.NewCond(locker)
var waitgroup sync.WaitGroup
func test(x int) {
cond.L.Lock()
// cond.Wait() //有wait必须有lock
fmt.Println("test",x)
time.Sleep(time.Second * 1)
defer func() {
cond.L.Unlock() //释放锁
waitgroup.Done() //减一个协程
}()
}
func aaaa(x int) {
cond.L.Lock()
cond.Wait() //有wait必须有lock
fmt.Println("aaaa",x)
time.Sleep(time.Second * 1)
defer func() {
cond.L.Unlock() //释放锁
waitgroup.Done() //减一个协程
}()
}
func bbbb(x int) {
fmt.Println("bbbb",x)
}
func main() {
for i := 0; i < 5; i++ {
go test(i)
go aaaa(i)
go bbbb(i)
waitgroup.Add(1*2)
}
fmt.Println("Signal:")
cond.Signal() //前面的cond就是表示唤醒加锁的:加wait就是唤醒一个加锁的协程 不加wait会唤醒所有没堵塞的加锁协程。
time.Sleep(time.Second * 20)
fmt.Println("Broadcast:")
cond.Broadcast() //唤醒剩下堵塞的
waitgroup.Wait() //保证所有协程执行完毕
}
// 加wait的
// Signal:
// 1
// Broadcast:
// 4
// 2
// 0
// 3
// 不加wait的
// Signal:
// 1
// 0
// 3
// 4
// Broadcast:
// 2
// 两个函数的协程:
// 第一个函数都执行了,第二个加了wait只执行了一次
// cond是只会执行加锁的协程,相当于加了一个标识,
// lock与ulock是表示
// wait是堵塞等待
// Signal会给信号疏通一个加锁协程
// Broadcast疏通所有剩下的加锁协程
// Signal:
// test 0
// test 1
// test 3
// test 2
// test 4
// aaaa 1
// Broadcast:
// aaaa 4
// aaaa 2
// aaaa 0
// aaaa 3
// 三个函数的
// Signal:
// bbbb 0
// bbbb 3
// bbbb 1
// bbbb 2
// bbbb 4
// test 0
// test 1
// test 4
// test 2
// test 3
// aaaa 1
// Broadcast:
// aaaa 4
// aaaa 3
// aaaa 0
// aaaa 2