在 Golang 中,sync.Cond 是一个非常有用的同步工具,它帮助多个goroutine 协作和同步。我们可以用它来让某些 Goroutine 等待特定的条件,直到其他 Goroutine 发出通知。
什么是 sync.Cond?
简单来说,sync.Cond 就是“条件变量”,它配合锁(sync.Mutex 或 sync.RWMutex)来控制多个 Goroutine 的行为。它有三个主要方法:
Wait():让当前的 goroutine 等待,直到收到通知。Signal():唤醒一个等待的 goroutine。Broadcast():唤醒所有等待的 goroutine。
基本使用
以下是一个简单的例子,展示了如何使用 sync.Cond 来控制 goroutine 的等待和通知:
package main
import (
"fmt"
"sync"
"time"
)
func worker(id int, cond *sync.Cond) {
cond.L.Lock()
defer cond.L.Unlock()
fmt.Printf("Worker %d is waiting...\n", id)
cond.Wait() // 等待信号
fmt.Printf("Worker %d is working now!\n", id)
}
func main() {
// 创建一个 Mutex 来锁住条件变量
mutex := &sync.Mutex{}
cond := sync.NewCond(mutex)
// 启动多个 Goroutine
for i := 1; i <= 3; i++ {
go worker(i, cond)
}
time.Sleep(2 * time.Second)
// 唤醒一个 Goroutine
fmt.Println("Main: Signaling one worker...")
cond.L.Lock()
cond.Signal()
cond.L.Unlock()
time.Sleep(2 * time.Second)
// 唤醒所有 Goroutine
fmt.Println("Main: Broadcasting to all workers...")
cond.L.Lock()
cond.Broadcast()
cond.L.Unlock()
time.Sleep(2 * time.Second)
}
解释
cond.L.Lock(): 锁住sync.Cond,确保条件变量的安全。cond.Wait(): 让当前 Goroutine 等待,直到它收到通知。cond.Signal(): 唤醒一个等待中的 Goroutine。cond.Broadcast(): 唤醒所有等待中的 Goroutine。
输出示例
Worker 1 is waiting...
Worker 2 is waiting...
Worker 3 is waiting...
Main: Signaling one worker...
Worker 1 is working now!
Main: Broadcasting to all workers...
Worker 2 is working now!
Worker 3 is working now!
实际应用:生产者-消费者
使用 sync.Cond 可以实现类似生产者-消费者的场景,生产者放入数据,消费者等待数据并处理。
package main
import (
"fmt"
"sync"
"time"
)
type Buffer struct {
data []int
mu sync.Mutex
cond *sync.Cond
}
func NewBuffer() *Buffer {
mu := sync.Mutex{}
return &Buffer{
data: []int{},
mu: mu,
cond: sync.NewCond(&mu),
}
}
func (b *Buffer) Produce(item int) {
b.mu.Lock()
defer b.mu.Unlock()
b.data = append(b.data, item)
fmt.Printf("Produced: %d\n", item)
// 通知消费者
b.cond.Signal()
}
func (b *Buffer) Consume() {
b.mu.Lock()
defer b.mu.Unlock()
for len(b.data) == 0 {
b.cond.Wait() // 等待生产者
}
item := b.data[0]
b.data = b.data[1:]
fmt.Printf("Consumed: %d\n", item)
}
func main() {
buffer := NewBuffer()
// 启动多个消费者
for i := 1; i <= 3; i++ {
go func(id int) {
for {
buffer.Consume()
}
}(i)
}
// 启动生产者
for i := 1; i <= 5; i++ {
buffer.Produce(i)
time.Sleep(1 * time.Second)
}
}
总结
sync.Cond结合了锁和条件变量,适合用于多个 Goroutine 之间的协作。- 使用
Wait()让 Goroutine 等待,使用Signal()或Broadcast()来通知它们继续执行。 sync.Cond常见的应用包括生产者-消费者、任务调度等需要等待与通知的场景。
5526

被折叠的 条评论
为什么被折叠?



