Share via


セマフォ オブジェクト

セマフォ オブジェクトは、0 から指定した最大値までのカウントを保持する同期オブジェクトです。 カウントは、スレッドがセマフォ オブジェクトの待機を完了するたびにデクリメントされ、スレッドがセマフォを解放するたびにインクリメントされます。 カウントが 0 に達すると、セマフォ オブジェクトの状態がシグナル通知されるまでスレッドが正常に待機できなくなります。 セマフォの状態は、そのカウントが 0 より大きい場合はシグナル状態に、0 の場合は非シグナル状態に設定されます。

セマフォ オブジェクトは、限られた数のユーザーをサポートできる共有リソースを制御する場合に役立ちます。 これは、リソースを共有するスレッドの数を指定した最大数に制限するゲートとして機能します。 たとえば、アプリケーションが作成するウィンドウの数に制限を設定する場合があります。 ウィンドウの上限と等しい最大カウントを持つセマフォを使用し、ウィンドウが作成されるたびにカウントを減らし、ウィンドウが閉じられるたびにインクリメントします。 アプリケーションは、各ウィンドウが作成される前に、 いずれかの待機関数 の呼び出しでセマフォ オブジェクトを指定します。 カウントが 0 の場合 (ウィンドウの制限に達したことを示します)、待機関数はウィンドウ作成コードの実行をブロックします。

スレッドは 、CreateSemaphore または CreateSemaphoreEx 関数を使用してセマフォ オブジェクトを作成します。 作成スレッドは、オブジェクトの初期カウントとカウントの最大値を指定します。 初期カウントは、0 未満でも最大値よりも大きくすることはできません。 作成スレッドでは、セマフォ オブジェクトの名前を指定することもできます。 他のプロセスのスレッドは、 OpenSemaphore 関数の呼び出しで名前を指定することで、既存のセマフォ オブジェクトへのハンドルを開くことができます。 ミューテックス、イベント、セマフォ、およびタイマー オブジェクトの名前の詳細については、「 プロセス間同期」を参照してください。

セマフォで複数のスレッドが待機している場合は、待機中のスレッドが選択されます。 先入れ先出し (FIFO) の順序は想定しないでください。 カーネル モードの APC などの外部イベントは、待機順序を変更できます。

セマフォの状態がシグナルに設定されているため、 いずれかの待機関数 が戻るたびに、セマフォの数は 1 ずつ減少します。 ReleaseSemaphore 関数は、セマフォのカウントを指定した量だけ増やします。 カウントを 0 より小さくしたり、最大値を超えたりすることはできません。

通常、セマフォの初期カウントは最大値に設定されます。 その後、保護されたリソースが使用されると、そのレベルからカウントがデクリメントされます。 または、初期カウントが 0 のセマフォを作成して、アプリケーションの初期化中に保護されたリソースへのアクセスをブロックすることもできます。 初期化後、 ReleaseSemaphore を使用して、カウントを最大値にインクリメントできます。

ミューテックス オブジェクトを所有するスレッドは、同じミューテックス オブジェクトの実行がブロックされずにシグナル通知されるまで繰り返し待機できます。 ただし、同じセマフォ オブジェクトを繰り返し待機するスレッドは、待機操作が完了するたびにセマフォのカウントをデクリメントします。カウントが 0 になると、スレッドはブロックされます。 同様に、ミューテックスを所有するスレッドのみが ReleaseMutex 関数を正常に呼び出すことができますが、どのスレッドでも ReleaseSemaphore を使用してセマフォ オブジェクトの数を増やすことができます。

スレッドは、待機 関数の呼び出しで同じセマフォ オブジェクトを繰り返し指定することで、セマフォの数を複数回減らすことができます。 ただし、同じセマフォの複数のハンドルを含む配列を使用して複数オブジェクト待機関数のいずれかを呼び出しても、複数のデクリメントは発生しません。

セマフォ オブジェクトの使用が完了したら、 CloseHandle 関数を呼び出してハンドルを閉じます。 セマフォ オブジェクトは、最後のハンドルが閉じられたときに破棄されます。 ハンドルを閉じてもセマフォ数には影響しません。そのため、ハンドルを閉じる前、またはプロセスが終了する前に ReleaseSemaphore を呼び出してください。 それ以外の場合、保留中の待機操作は、タイムアウト値が指定されているかどうかに応じて、タイムアウトするか無期限に続行されます。

セマフォ オブジェクトの使用