Semaphore と SemaphoreSlim

System.Threading.Semaphore クラスは、名前付き (システム全体) またはローカルのセマフォを表します。 このクラスは Win32 セマフォ オブジェクトをラップする Thin ラッパーです。 Win32 セマフォはカウント セマフォで、リソースのプールへのアクセス制御に使用できます。

SemaphoreSlim クラスは、軽量で高速なセマフォを表します。このセマフォは、待機時間が非常に短くなると予測される場合に、単一のプロセス内での待機に使用できます。 SemaphoreSlim は、共通言語ランタイム (CLR: Common Language Runtime) によって提供される同期プリミティブに最大限依存します。 ただし、複数のセマフォでの待機をサポートするために、必要に応じて限定的に初期化されるカーネル ベースの待機ハンドルも用意されています。 SemaphoreSlim では、キャンセル トークンの使用もサポートされていますが、名前付きセマフォ、および同期用の待機ハンドルの使用はサポートされていません。

制限されたリソースの管理

スレッドは、WaitHandle クラスから継承した WaitOne メソッドを呼び出して、セマフォに入ります。 呼び出しが返されると、セマフォのカウントはデクリメントされます。 スレッドがエントリを要求し、カウントがゼロの場合、スレッドはブロックされます。 スレッドは Semaphore.Release メソッドを呼び出してセマフォを解放するので、ブロックされたスレッドは入ることができます。 ブロックされたスレッドがセマフォに入るための、保証された順序 (先入れ先出し (FIFO) や後入れ先出し (LIFO) など) はありません。

スレッドは、WaitOne メソッドを繰り返し呼び出すと、複数回セマフォに入ることができます。 セマフォを解放するには、スレッドは、Release() メソッドのオーバーロードを同じ回数だけ呼び出すか、Release(Int32) メソッドのオーバーロードを呼び出して、解放するエントリの番号を指定します。

セマフォおよびスレッド ID

Semaphore クラスは、WaitOne および Release メソッドへの呼び出しで、スレッド ID を適用しません。 たとえば、セマフォのシナリオの一般的な使い方として、作成側のスレッドと消費側のスレッドがあります。一方のスレッドは常にセマフォのカウントをインクリメントし、もう一方は常にデクリメントします。

プログラマは、スレッドによるセマフォの解放回数が多くなりすぎないように注意する必要があります。 たとえば、セマフォのカウントの最大値が 2 で、スレッド A とスレッド B の両方がセマフォに入ったとします。 スレッド B のプログラミング エラーによって Release が 2 回呼び出された場合、呼び出しは 2 回とも成功します。 セマフォのカウントはいっぱいなので、スレッド A が Release を呼び出すと、SemaphoreFullException がスローされます。

名前付きのセマフォ

Windows オペレーティング システムでは、セマフォに名前を付けることができます。 名前付きのセマフォはシステム全体で使用されます。 つまり、いったん名前付きのセマフォを作成すると、すべてのプロセスのすべてのスレッドがそれを参照できます。 したがって、名前付きのセマフォを使用して、スレッドだけでなくプロセスのアクティビティも同期できます。

名前付きのシステム セマフォを表す Semaphore オブジェクトを作成するには、名前を指定するいずれかのコンストラクターを使用します。

メモメモ

名前付きのセマフォはシステム全体で使用されるため、複数の Semaphore オブジェクトで同じ名前付きセマフォを表すことができます。コンストラクターまたは Semaphore.OpenExisting メソッドを呼び出すたびに、新しい Semaphore オブジェクトが作成されます。同じ名前を繰り返し指定すると、同じ名前付きセマフォを表す複数のオブジェクトを作成できます。

名前付きセマフォを使用する場合は注意してください。 それらはシステム全体で使用されるので、別のプロセスが同じ名前を使用すると、予期せずにセマフォに入る場合があります。 悪意のあるコードが同じコンピューターで実行されると、サービス拒否攻撃の基本としてこれが使用される場合があります。

アクセス制御セキュリティを使用して、名前付きのセマフォを表す Semaphore オブジェクトを保護します。できれば System.Security.AccessControl.SemaphoreSecurity オブジェクトを指定するコンストラクターを使用します。 また、Semaphore.SetAccessControl メソッドを使用してアクセス制御セキュリティを適用できます。ただし、こうすると、セマフォが作成されてから保護されるまでの間に、脆弱性が生じます。 アクセス制御セキュリティでセマフォを保護すると、悪意のある攻撃を防ぐのに役立ちますが、予期しない名前の衝突の問題解決にはなりません。

参照

参照

Semaphore

SemaphoreSlim

その他の技術情報

スレッド処理オブジェクトと機能