条件变量

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

条件变量使线程能够以原子方式释放锁并进入休眠状态。 它们可与关键部分或超薄读取器/编写器 (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 函数将验证当前锁请求是否与现有所有者兼容。 如果是,请获取锁;否则为睡眠。 有关更详细的示例,请参阅 使用条件变量

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

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

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

使用条件变量