sync.Cond
是 Go 语言标准库中 sync
包提供的一个条件变量工具,它用于协调想要访问共享资源的多个 goroutine 之间的同步。理解 sync.Cond
的工作原理,我们可以将其比喻为一种等候室的机制:
工作原理(通俗解释)
假设有一个等候室(sync.Cond
),在这个等候室里,多个人(goroutine)可能因为某种原因需要等待(比如等待医生来)。这个等候室提供了三个主要的功能:
- 等待(Wait):当某人需要等待某件事发生(比如等待医生来)时,他可以在等候室中等待。这时,他就坐下来(goroutine 休眠),释放了他在等候室中占用的座位(释放锁),以便让新来的人(其他 goroutine)有地方坐。
- 通知(Signal):当医生来了(条件满足)时,工作人员(另一个 goroutine)会通知等候室中的一个正在等待的人(唤醒一个等待的 goroutine),告诉他可以进行他需要的操作了。
- 广播(Broadcast):如果医生宣布他可以看所有的病人了(条件对所有等待者都满足),工作人员会通知等候室里所有的人(唤醒所有等待的 goroutine)。
注意事项
- 锁定和解锁 :使用
sync.Cond
必须和锁(通常是sync.Mutex
或sync.RWMutex
)一起使用。在调用Wait
方法之前,你需要手动锁定;Wait
会自动释放锁,并在条件满足,被唤醒后重新锁定。 - 避免虚假唤醒 :即使没有接到通知(Signal/Broadcast),
Wait
有时也会返回。因此,在Wait
后再次检查条件是否真的满足是一个好习惯。 - 正确使用 Signal 和 Broadcast :使用
Signal
是指你知道有其他 goroutine 正在等待这个特定的条件变量,并且你想唤醒一个;使用Broadcast
是知道你想唤醒所有等待的 goroutine。
如何使用
下面是一个简单的使用 sync.Cond
的例子:
go
package main
import (
"sync"
"fmt"
)
func main() {
var mutex sync.Mutex
cond := sync.NewCond(&mutex)
go func() {
mutex.Lock()
// 这里是等待条件满足的逻辑
cond.Wait() // 等待条件变量的通知
fmt.Println("条件满足,继续执行")
mutex.Unlock()
}()
// 模拟条件满足的情况
mutex.Lock()
cond.Signal() // 发出条件已经满足的信号
mutex.Unlock()
// 让 main goroutine 等待,以便观察输出
select {}
}
我们创建了一个条件变量 cond
和一个互斥锁 mutex
。一个 goroutine 会在条件变量上等待,直到另一个 goroutine 通过调用 Signal
方法通知条件满足。