40.3 条件变量

条件变量(condition variable) 用于让线程阻塞等待某一事件发生。 线程可在条件变量上等待,直到其他线程通知该条件变量后被唤醒。

条件变量与一个互斥锁关联,在逻辑上还对应某个条件。 为保证正常工作,必须先获取互斥锁,随后等待线程循环检查条件, 并在条件变量上等待。示例如下:

(with-mutex mutex
  (while (not global-variable)
    (condition-wait cond-var)))

互斥锁保证操作原子性,循环则用于增强鲁棒性—可能存在虚假通知。

同理,通知条件变量前也必须持有关联的互斥锁。 标准且推荐的做法是:先获取互斥锁,修改与条件相关的状态,再发送通知:

(with-mutex mutex
  (setq global-variable (some-computation))
  (condition-notify cond-var))
Function: make-condition-variable mutex &optional name

创建与 mutex 关联的新条件变量。若指定 name,则为条件变量命名, 名称必须为字符串。该名称仅用于调试,对 Emacs 无实际意义。

Function: condition-variable-p object

object 为条件变量对象,该函数返回 t,否则返回 nil

Function: condition-wait cond

让当前线程在条件变量 cond 上等待通知。 函数会阻塞,直到条件变量被通知,或当前线程收到 thread-signal 信号。

未持有条件变量关联的互斥锁就调用 condition-wait 属于错误操作。

condition-wait 在等待期间会释放关联互斥锁, 允许其他线程获取该锁以发送条件通知。

Function: condition-notify cond &optional all

通知条件变量 cond。调用前必须持有其关联互斥锁。 默认仅唤醒一个等待线程;若 allnil,则唤醒所有在 cond 上等待的线程。

condition-notify 会释放关联互斥锁, 允许其他线程获取该锁以继续等待条件。

Function: condition-name cond

返回 cond 的名称,即创建时传给 make-condition-variable 的名称。

Function: condition-mutex cond

返回与 cond 关联的互斥锁。注意,关联的互斥锁不可更改。