Go 语言 条件变量的等待和通知机制

Go阿木 发布于 2025-06-22 5 次阅读


摘要:Go 语言中的条件变量是协程同步的一种重要机制,它允许协程在满足特定条件之前挂起,并在条件成立时被唤醒。本文将围绕Go语言的条件变量,详细介绍其等待和通知机制,并通过实际代码示例进行深入剖析。

一、

在并发编程中,协程之间的同步是一个常见且重要的任务。Go 语言提供了多种同步原语,如互斥锁(Mutex)、条件变量(Condition)等。其中,条件变量是一种特殊的锁,它允许协程在满足特定条件之前挂起,并在条件成立时被唤醒。本文将重点介绍Go语言的条件变量及其等待和通知机制。

二、条件变量的基本概念

条件变量是一种特殊的锁,它允许协程在满足特定条件之前挂起,并在条件成立时被唤醒。在Go语言中,条件变量通常与互斥锁(Mutex)一起使用,以确保在访问共享资源时的线程安全。

条件变量的主要特点如下:

1. 条件变量必须与互斥锁一起使用。

2. 条件变量提供两个操作:Wait和Signal。

3. Wait操作使当前协程挂起,直到另一个协程调用Signal或Broadcast操作。

4. Signal操作唤醒一个或多个等待的协程。

三、条件变量的使用方法

1. 创建互斥锁和条件变量

go

var mutex sync.Mutex


var condition = sync.NewCond(&mutex)


2. 使用Wait操作挂起协程

go

mutex.Lock()


// 执行一些操作...


for condition.Wait() {


// 等待条件成立


}


// 条件成立,继续执行...


mutex.Unlock()


3. 使用Signal操作唤醒协程

go

mutex.Lock()


// 执行一些操作...


condition.Signal() // 唤醒一个等待的协程


// 或者


condition.Broadcast() // 唤醒所有等待的协程


mutex.Unlock()


四、条件变量的实际应用

以下是一个使用条件变量实现生产者-消费者模型的示例:

go

package main

import (


"fmt"


"sync"


"time"


)

type Product struct {


id int


data string


}

var (


products []Product


mutex sync.Mutex


condition = sync.NewCond(&mutex)


)

func producer() {


for i := 0; i < 10; i++ {


mutex.Lock()


products = append(products, Product{id: i, data: fmt.Sprintf("product %d", i)})


condition.Signal()


mutex.Unlock()


time.Sleep(time.Millisecond 100)


}


}

func consumer() {


for {


mutex.Lock()


for len(products) == 0 {


condition.Wait()


}


product := products[0]


products = products[1:]


fmt.Printf("Consumer got product %d: %s", product.id, product.data)


mutex.Unlock()


time.Sleep(time.Millisecond 200)


}


}

func main() {


var wg sync.WaitGroup


wg.Add(1)


go producer()


wg.Add(1)


go consumer()


wg.Wait()


}


在这个示例中,生产者协程负责生产产品并将其添加到共享列表中,消费者协程则从列表中取出产品并消费。条件变量用于确保消费者在产品列表为空时挂起,直到生产者添加新产品。

五、总结

本文详细介绍了Go语言中的条件变量及其等待和通知机制。通过实际代码示例,我们了解了条件变量的使用方法及其在实际应用中的优势。在并发编程中,条件变量是一种非常有用的同步原语,可以帮助我们实现复杂的同步逻辑。