# sync.Cond
# 介绍
sync.Cond 是 Go 语言标准库中的一个条件变量,用于在多个 goroutine 之间进行同步和通信。它允许一个或多个 goroutine 等待某个条件变为真,然后通知其他等待的 goroutine 继续执行。
type Cond struct { | |
noCopy noCopy | |
// L is held while observing or changing the condition | |
L Locker // 每个 Cond 都有一个关联的 Locker L,在改变条件和调用 Wait 方法时,需要先获取 L 的锁 | |
notify notifyList // 通知列表 | |
checker copyChecker // 复制检查器 | |
} |
# 方法
# NewCond 构造函数
func NewCond(l Locker) *Cond { | |
return &Cond{L: l} | |
} |
# Wait 等待
Wait 方法会使当前 goroutine 进入等待状态,直到收到通知或被广播。调用 Wait 方法前,需要先获取 c.L 的锁,并在调用 Wait 方法后释放 c.L 的锁。Wait 方法会自动释放 c.L 的锁,并在收到通知或被广播后重新获取 c.L 的锁。
func (c *Cond) Wait() { | |
c.checker.check() | |
t := runtime_notifyListAdd(&c.notify) | |
c.L.Unlock() | |
runtime_notifyListWait(&c.notify, t) | |
c.L.Lock() | |
} |
# Signal 通知一个等待的 goroutine
Signal 方法会通知一个等待的 goroutine 继续执行。
允许但不要求调用者在调用过程中持有 c.L 的锁。
func (c *Cond) Signal() { | |
c.checker.check() | |
runtime_notifyListNotifyOne(&c.notify) | |
} |
# Broadcast 通知所有等待的 goroutine
Broadcast 方法会通知所有等待的 goroutine 继续执行。
允许但不要求调用者在调用过程中持有 c.L 的锁。
func (c *Cond) Broadcast() { | |
c.checker.check() | |
runtime_notifyListNotifyAll(&c.notify) | |
} |
# 使用场景
sync.Cond 通常用于以下场景:
- 生产者 - 消费者模型:当生产者生产出产品后,通知消费者进行消费;当消费者消费完产品后,通知生产者继续生产。在这种情况下,可以使用
sync.Cond来实现生产者和消费者之间的同步。
var ( | |
mux = sync.Mutex{} | |
cond = sync.NewCond(&mux) | |
queue []int | |
) | |
func producer(count int) { | |
for i := 0; i < count; i++ { | |
mux.Lock() | |
queue = append(queue, i+1) | |
fmt.Println("produced:", i+1) | |
cond.Signal() | |
mux.Unlock() | |
} | |
} | |
func comsumer() { | |
for { | |
mux.Lock() | |
for len(queue) == 0 { | |
cond.Wait() | |
} | |
fmt.Println("consumed:", queue[0]) | |
queue = queue[1:] | |
mux.Unlock() | |
} | |
} | |
func main() { | |
go comsumer() | |
go producer(100) | |
time.Sleep(time.Second) | |
} |
- 多协程同步:当多个 goroutine 需要等待某个条件变为真时,可以使用
sync.Cond来实现同步。
# 使用方法
sync.Cond 的使用方法如下:
- 创建一个
sync.Cond对象:可以使用sync.NewCond(&sync.Mutex{})来创建一个sync.Cond对象,其中sync.Mutex是用于保护条件的互斥锁。 - 调用
Wait方法:在需要等待某个条件变为真的地方,调用sync.Cond对象的Wait方法,该方法会使当前 goroutine 进入等待状态,直到收到通知或被广播。 - 调用
Signal或Broadcast方法:在条件变为真的地方,调用sync.Cond对象的Signal或Broadcast方法,该方法会通知一个或所有等待的 goroutine 继续执行。
# 注意事项
- 在调用
Wait方法前,需要先获取sync.Cond对象的互斥锁。 - 在调用
Signal或Broadcast方法前,需要先获取sync.Cond对象的互斥锁。 sync.Cond对象的互斥锁需要在调用Wait方法前获取,并在调用Wait方法后释放,以确保在等待期间不会发生竞争条件。sync.Cond对象的互斥锁需要在调用Signal或Broadcast方法前获取,并在调用Signal或Broadcast方法后释放,以确保在通知期间不会发生竞争条件。
# 总结
sync.Cond 是 Go 语言标准库中的一个条件变量,用于在多个 goroutine 之间进行同步和通信。它允许一个或多个 goroutine 等待某个条件变为真,然后通知其他等待的 goroutine 继续执行。 sync.Cond 的使用方法简单,但在使用时需要注意互斥锁的获取和释放,以避免竞争条件。