条件変数
条件変数は、スレッドが特定の条件が発生するまで待機できるようにする同期プリミティブです。 条件変数は、プロセス間で共有できないユーザー モード オブジェクトです。
条件変数を使用すると、スレッドはロックをアトミックに解放し、スリープ状態に入ります。 重要なセクションまたはスリム リーダー/ライター (SRW) ロックと共に使用できます。 条件変数は、待機中のスレッドを "1 つスリープ解除" または "すべてウェイク" する操作をサポートします。 スレッドが目覚めた後、スレッドがスリープ状態になったときに解放されたロックを再取得します。
呼び出し元は、CONDITION_VARIABLE 構造体を割り当て、initializeConditionVariableを呼び出して初期化するか (構造体を動的に初期化する)、定数 CONDITION_VARIABLE_INIT を構造体変数に割り当てる (構造体を静的に初期化する) 必要があることに注意してください。
Windows Server 2003 および Windows XP: 条件変数はサポートされていません。
条件変数関数を次に示します。
条件変数関数 | 形容 |
---|---|
InitializeConditionVariableの | 条件変数を初期化します。 |
SleepConditionVariableCS | 指定した条件変数をスリープ状態にし、指定したクリティカル セクションをアトミック操作として解放します。 |
SleepConditionVariableSRW | 指定した条件変数をスリープ状態にし、指定した SRW ロックをアトミック操作として解放します。 |
WakeAllConditionVariableの | 指定した条件変数を待機しているすべてのスレッドをウェイクアップします。 |
WakeConditionVariableの | 指定された条件変数を待機している 1 つのスレッドをスリープ解除します。 |
次の擬似コードは、条件変数の一般的な使用パターンを示しています。
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
関数は、現在のロック要求が既存の所有者と互換性があることを確認します。 その場合は、ロックを取得します。それ以外の場合はスリープ。 詳細な例については、「条件変数の使用」を参照してください。
条件変数は、スプリアス ウェイクアップ (明示的なウェイクアップに関連付けられていないもの) と盗まれたウェイクアップ (別のスレッドが起動スレッドの前に実行を管理) の対象となります。 そのため、スリープ操作が戻った後に述語 (通常、ループ中に で) を再確認する必要があります。
WakeConditionVariable使用するか、条件変数に関連付けられているロックの内側または外側に WakeAllConditionVariableをして、他のスレッドをウェイクアップできます。 通常は、コンテキスト スイッチの数を減らすために、他のスレッドをウェイクする前にロックを解除することをお勧めします。
多くの場合、同じロックで複数の条件変数を使用すると便利です。 たとえば、リーダー/ライター ロックの実装では、1 つのクリティカル セクションが使用されますが、リーダーとライターには個別の条件変数が使用される場合があります。
関連トピック
-
条件変数 を使用した