条件变量

条件变量是同步基元,使线程能够等待特定条件出现。 条件变量是不能跨进程共享的用户模式对象。

条件变量使线程能够原子释放锁并进入睡眠状态。 它们可与关键节或精简的读取器/编写器(SRW)锁一起使用。 条件变量支持“唤醒一个”或“唤醒所有”等待线程的作。 线程唤醒后,它会在线程进入睡眠状态时重新获取释放的锁。

请注意,调用方必须分配 CONDITION_VARIABLE 结构,并通过调用 InitializeConditionVariable(动态初始化结构)或将常量 CONDITION_VARIABLE_INIT 分配给结构变量(以静态方式初始化结构)来初始化它。

Windows Server 2003 和 Windows XP:不支持 条件变量。

以下是条件变量函数。

条件变量函数 描述
InitializeConditionVariable 初始化条件变量。
SleepConditionVariableCS 在指定的条件变量上睡眠,并将指定的关键节作为原子作释放。
SleepConditionVariableSRW 在指定的条件变量上休眠,并将指定的 SRW 锁作为原子作释放。
WakeAllConditionVariable 唤醒所有等待指定条件变量的线程。
WakeConditionVariable 唤醒等待指定条件变量的单个线程。

 

以下伪代码演示条件变量的典型使用模式。

CRITICAL_SECTION CritSection;
CONDITION_VARIABLE ConditionVar;

void PerformOperationOnSharedData()
{ 
   EnterCriticalSection(&CritSection);

   // Wait until the predicate is TRUE

   while( TestPredicate() == FALSE )
   {
      SleepConditionVariableCS(&ConditionVar, &CritSection, INFINITE);
   }

   // The data can be changed safely because we own the critical 
   // section and the predicate is TRUE

   ChangeSharedData();

   LeaveCriticalSection(&CritSection);

   // If necessary, signal the condition variable by calling
   // WakeConditionVariable or WakeAllConditionVariable so other
   // threads can wake
}

例如,在读取器/编写器锁的实现中,TestPredicate 函数将验证当前锁请求是否与现有所有者兼容。 如果是,请获取锁;否则,请睡觉。 有关更详细的示例,请参阅 使用条件变量

条件变量受到虚假唤醒(与显式唤醒无关的唤醒)和被盗唤醒(另一个线程设法在唤醒线程之前运行)。 因此,在睡眠作返回后,应重新检查谓词(通常位于 循环中)。

可以使用 WakeConditionVariableWakeAllConditionVariable 与条件变量关联的锁内外唤醒其他线程。 在唤醒其他线程之前,最好释放锁以减少上下文切换的数量。

使用同一锁的多个条件变量通常很方便。 例如,读取器/编写器锁的实现可能使用单个关键部分,但针对读取器和编写器使用不同的条件变量。

使用条件变量