Golang sync.Cond 使用入门

在 Golang 中,sync.Cond 是一个非常有用的同步工具,它帮助多个goroutine 协作和同步。我们可以用它来让某些 Goroutine 等待特定的条件,直到其他 Goroutine 发出通知。

什么是 sync.Cond

简单来说,sync.Cond 就是“条件变量”,它配合锁(sync.Mutexsync.RWMutex)来控制多个 Goroutine 的行为。它有三个主要方法:

  1. Wait():让当前的 goroutine 等待,直到收到通知。
  2. Signal():唤醒一个等待的 goroutine。
  3. 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)
}

解释

  1. cond.L.Lock(): 锁住 sync.Cond,确保条件变量的安全。
  2. cond.Wait(): 让当前 Goroutine 等待,直到它收到通知。
  3. cond.Signal(): 唤醒一个等待中的 Goroutine。
  4. 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 常见的应用包括生产者-消费者、任务调度等需要等待与通知的场景。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值