sync.Cond用于协程间同步,核心包含互斥锁、Wait()等待和Signal/Broadcast通知。使用时需先加锁,用for循环检查条件并调用Wait,其他协程修改状态后调用Signal唤醒,适用于状态变化通知场景,如生产者-消费者模型。

在Go语言中,sync.Cond 是一种用于协程间同步的机制,它允许一个或多个协程等待某个条件成立,而另一个协程在条件成立后通知它们继续执行。它常用于“生产者-消费者”模型或资源就绪通知等场景。虽然 channel 更常用于协程通信,但在某些需要明确等待某个状态改变的场景下,sync.Cond 更加直观高效。
sync.Cond 包含三个核心部分:
使用流程通常如下:
下面是一个使用 sync.Cond 等待任务到来的简单示例:
立即学习“go语言免费学习笔记(深入)”;
package main
<p>import (
"fmt"
"sync"
"time"
)</p><p>type TaskQueue struct {
tasks []string
cond *sync.Cond
}</p><p>func (q *TaskQueue) AddTask(task string) {
q.cond.L.Lock()
defer q.cond.L.Unlock()
q.tasks = append(q.tasks, task)
fmt.Println("任务添加:", task)
q.cond.Signal() // 唤醒一个等待的消费者
}</p><p>func (q *TaskQueue) GetTask() string {
q.cond.L.Lock()
defer q.cond.L.Unlock()</p><pre class='brush:php;toolbar:false;'>// 使用 for 而不是 if,防止虚假唤醒
for len(q.tasks) == 0 {
q.cond.Wait()
}
task := q.tasks[0]
q.tasks = q.tasks[1:]
return task}
func main() { var mu sync.Mutex queue := &TaskQueue{ tasks: make([]string, 0), cond: sync.NewCond(&mu), }
// 消费者协程
go func() {
for {
task := queue.GetTask()
fmt.Println("处理任务:", task)
}
}()
// 生产者协程
for i := 1; i <= 5; i++ {
time.Sleep(1 * time.Second)
queue.AddTask(fmt.Sprintf("任务-%d", i))
}
time.Sleep(3 * time.Second)}
输出结果类似:
任务添加: 任务-1使用 sync.Cond 时,有几个关键点必须注意:
sync.Cond 适合用于“状态变化通知”类场景,比如:
但在大多数通信场景中,Go 更推荐使用 channel。例如,上面的例子也可以用无缓冲 channel 实现生产者消费者。sync.Cond 更适合已有共享状态且需要精确控制唤醒逻辑的场景。
基本上就这些。sync.Cond 不复杂但容易忽略细节,尤其是锁和循环判断的配合。用好它,能写出更高效的同步逻辑。
以上就是Golang条件变量使用 sync.Cond实践的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号