sync包之Cond | 青训营笔记

99 阅读2分钟

5. sync.Cond 原理

sync.Cond 是 Go 语言提供的内置并发安全的条件变量,开箱即用。sync.Cond 的原理非常简单,只有三个方法,Wait、Signal 和 Broadcast。Wait 方法用于等待条件变量,Signal 方法用于唤醒一个等待的协程,Broadcast 方法用于唤醒所有等待的协程。

sync.Cond 的内部结构如下:

type Cond struct {
    noCopy noCopy
    L Locker
    notify  notifyList
}

sync.Cond 内部有一个 Locker 接口,同时有一个 notifyList,notifyList 的结构如下:

type notifyList struct {
    wait   int32
    notify int32
    lock   uintptr
    head   unsafe.Pointer // *waitNode
    tail   unsafe.Pointer // *waitNode
}

notifyList 内部有一个 wait 和 notify,分别用于存储等待的协程数和唤醒的协程数,同时有一个 head 和 tail,分别用于存储等待的协程的头和尾。

5.1 sync.Cond 的 Wait 方法

sync.Cond 的 Wait 方法用于等待条件变量,其原型如下:

func (c *Cond) Wait()

Wait 方法的实现非常简单,只有两个步骤:

  1. 将等待的协程数加 1
  2. 解锁
  3. 等待信号量
  4. 加锁

5.2 sync.Cond 的 Signal 方法

sync.Cond 的 Signal 方法用于唤醒一个等待的协程,其原型如下:

func (c *Cond) Signal()

Signal 方法的实现非常简单,只有两个步骤:

  1. 将唤醒的协程数加 1
  2. 唤醒一个等待的协程

5.3 sync.Cond 的 Broadcast 方法

sync.Cond 的 Broadcast 方法用于唤醒所有等待的协程,其原型如下:

func (c *Cond) Broadcast()

Broadcast 方法的实现非常简单,只有两个步骤:

  1. 将唤醒的协程数加 1
  2. 唤醒所有等待的协程

6. sync.Cond 的使用

sync.Cond 的使用非常简单,直接声明变量即可,不需要初始化。sync.Cond 的声明如下:

var cond = sync.Cond{}

sync.Cond 的操作如下:

cond.Wait()      // 等待条件变量
cond.Signal()    // 唤醒一个等待的协程
cond.Broadcast() // 唤醒所有等待的协程

7. sync.Cond 的注意事项

  • sync.Cond 不能在创建后再进行复制操作。
  • sync.Cond 与其他结构不同,它不是一个结构体,因此我们在声明的时候只需要声明变量即可,不需要初始化。