System.Threading.Semaphore クラスは、名前付き (システム全体) またはローカル セマフォを表します。 これは、Win32 セマフォ オブジェクトのシン ラッパーです。 Win32 セマフォはカウント セマフォであり、リソース プールへのアクセスを制御するために使用できます。
SemaphoreSlim クラスは、待機時間が非常に短いと予想される場合に、1 つのプロセス内で待機するために使用できる軽量で高速なセマフォを表します。 SemaphoreSlim は、共通言語ランタイム (CLR) によって提供される同期プリミティブに可能な限り依存します。 ただし、複数のセマフォでの待機をサポートするために、必要に応じて遅延初期化されたカーネル ベースの待機ハンドルも提供します。 SemaphoreSlim ではキャンセル トークンの使用もサポートされていますが、名前付きセマフォや同期の待機ハンドルの使用はサポートされていません。
制限付きリソースの管理
スレッドは、System.Threading.Semaphore オブジェクトの場合はWaitHandle クラスから継承されるWaitOne メソッドを呼び出すことによってセマフォに入り、SemaphoreSlim オブジェクトの場合はSemaphoreSlim.WaitまたはSemaphoreSlim.WaitAsyncメソッドを呼び出します。 呼び出しが戻ると、セマフォのカウントがデクリメントされます。 スレッドがエントリを要求し、カウントが 0 の場合、スレッドはブロックします。 スレッドが Semaphore.Release または SemaphoreSlim.Release メソッドを呼び出してセマフォを解放すると、ブロックされたスレッドの入力が許可されます。 ブロックされたスレッドがセマフォに入る場合、先入れ先出し (FIFO) や最終入り先出し (LIFO) などの順序は保証されません。
スレッドは、 System.Threading.Semaphore オブジェクトの WaitOne メソッドまたは SemaphoreSlim オブジェクトの Wait メソッドを繰り返し呼び出すことによって、セマフォを複数回入力できます。 セマフォを解放するには、スレッドは、 Semaphore.Release() または SemaphoreSlim.Release() メソッドのオーバーロードを同じ回数だけ呼び出すか、 Semaphore.Release(Int32) または SemaphoreSlim.Release(Int32) メソッドのオーバーロードを呼び出して、解放するエントリの数を指定します。
セマフォとスレッド ID
2 つのセマフォ型は、 WaitOne、 Wait、 Release、および SemaphoreSlim.Release メソッドの呼び出しにスレッド ID を適用しません。 たとえば、セマフォの一般的な使用シナリオには、プロデューサー スレッドとコンシューマー スレッドが含まれます。1 つのスレッドは常にセマフォ数をインクリメントし、もう 1 つのスレッドは常にそれを減らします。
スレッドがセマフォを解放しすぎないようにするのはプログラマの責任です。 たとえば、セマフォの最大数が 2 で、そのスレッド A とスレッド B の両方がセマフォに入ったとします。 スレッド B のプログラミング エラーにより、 Release
が 2 回呼び出された場合、両方の呼び出しが成功します。 セマフォのカウントがいっぱいになり、スレッド A が最終的に Release
を呼び出すと、 SemaphoreFullException がスローされます。
名前付きセマフォ
Windows オペレーティング システムでは、セマフォに名前を付けることができます。 名前付きセマフォはシステム全体です。 つまり、名前付きセマフォが作成されると、すべてのプロセスのすべてのスレッドに表示されます。 したがって、名前付きセマフォを使用して、プロセスとスレッドのアクティビティを同期できます。
名前を指定するコンストラクターのいずれかを使用して、名前付きシステム セマフォを表す Semaphore オブジェクトを作成できます。
注
名前付きセマフォはシステム全体であるため、同じ名前付きセマフォを表す複数の Semaphore オブジェクトを持つことができます。 コンストラクターまたは Semaphore.OpenExisting メソッドを呼び出すたびに、新しい Semaphore オブジェクトが作成されます。 同じ名前を指定すると、同じ名前付きセマフォを表す複数のオブジェクトが繰り返し作成されます。
名前付きセマフォを使用するときは注意してください。 これらはシステム全体であるため、同じ名前を使用する別のプロセスが予期せずセマフォに入る可能性があります。 同じコンピューターで実行されている悪意のあるコードでは、これをサービス拒否攻撃の基礎として使用する可能性があります。
アクセス制御セキュリティを使用して、名前付きセマフォを表す Semaphore オブジェクトを保護します。可能な場合は、 System.Security.AccessControl.SemaphoreSecurity オブジェクトを指定するコンストラクターを使用します。 Semaphore.SetAccessControlメソッドを使用してアクセス制御セキュリティを適用することもできますが、セマフォが作成されてから保護されてからの間に、脆弱性の期間が残ります。 アクセス制御のセキュリティでセマフォを保護すると、悪意のある攻撃を防ぐことができますが、意図しない名前の競合の問題は解決しません。
こちらも参照ください
.NET