条件变量
本页依据 文档基线与后续更新 中记录的 Zephyr main 快照更新。
条件变量让线程等待受互斥量保护的应用状态发生变化。它本身不保存“已经通知过几次”, 没有等待者时发出的 signal 不会像信号量计数那样留待以后消费。
等待流程
调用 k_condvar_wait() 前,线程先持有配套互斥量。wait 原子地释放锁并加入等待,
返回前重新获取同一把锁。线程醒来后必须再次检查条件,因为其他线程可能已经消费了资源。
#include <zephyr/kernel.h>
K_MUTEX_DEFINE(value_lock);
K_CONDVAR_DEFINE(value_changed);
static bool ready;
static int value;
int consume_value(int *output)
{
int result;
k_mutex_lock(&value_lock, K_FOREVER);
while (!ready) {
int rc = k_condvar_wait(&value_changed, &value_lock, K_FOREVER);
if (rc != 0) {
k_mutex_unlock(&value_lock);
return rc;
}
}
result = value;
ready = false;
k_mutex_unlock(&value_lock);
*output = result;
return 0;
}
void publish_value(int next)
{
k_mutex_lock(&value_lock, K_FOREVER);
value = next;
ready = true;
k_condvar_signal(&value_changed);
k_mutex_unlock(&value_lock);
}
这是单槽状态示例,新发布可能替换尚未消费的旧值;需要保留所有值时使用消息队列。
示例通过返回值报告状态,成功时才写入 output。
signal、broadcast 与超时
k_condvar_signal() 唤醒一个等待者,k_condvar_broadcast() 唤醒全部等待者。
状态更新和条件检查应使用同一把互斥量。用 if 代替示例中的 while,可能在竞争
或不满足条件的唤醒后继续处理错误状态。
限时等待应检查返回值,并在返回时处理重新取得的互斥量。如果整个操作有总超时, 每次循环要按剩余时间等待,不能每次唤醒后重新给予完整超时。 不要递归多次持锁后依赖一次 wait 释放全部持锁层次;通常在持锁深度为 1 时等待。 条件变量的等待路径依赖线程与互斥量,不用于 ISR 阻塞。