Semaphore と SemaphoreSlimSemaphore and SemaphoreSlim

System.Threading.Semaphore クラスは、名前付きセマフォ (システム全体) またはローカル セマフォを表します。The System.Threading.Semaphore class represents a named (systemwide) or local semaphore. これは、Win32 セマフォ オブジェクトの Thin ラッパーです。It is a thin wrapper around the Win32 semaphore object. Win32 セマフォは、リソースのプールへのアクセスの制御に使用できるカウント セマフォです。Win32 semaphores are counting semaphores, which can be used to control access to a pool of resources.

SemaphoreSlim クラスは軽量で高速のセマフォを表しており、非常に短い待機時間が期待されている場合に単一プロセス内で待機のために使用できます。The SemaphoreSlim class represents a lightweight, fast semaphore that can be used for waiting within a single process when wait times are expected to be very short. SemaphoreSlim は、共通言語ランタイム (CLR) により提供される同期プリミティブに可能な限り依存します。SemaphoreSlim relies as much as possible on synchronization primitives provided by the common language runtime (CLR). ただし、複数のセマフォでの待機をサポートする必要がある場合は、遅れて初期化されるカーネル ベースの待機ハンドルも提供します。However, it also provides lazily initialized, kernel-based wait handles as necessary to support waiting on multiple semaphores. SemaphoreSlim はキャンセル トークンの使用もサポートしていますが、名前付きセマフォや、同期での待機ハンドルの使用はサポートしていません。SemaphoreSlim also supports the use of cancellation tokens, but it does not support named semaphores or the use of a wait handle for synchronization.

制限されているリソースの管理Managing a Limited Resource

スレッドは、WaitOne メソッドを呼び出してセマフォに入ります。このメソッドは WaitHandle クラスから継承されるか (System.Threading.Semaphore オブジェクトの場合)、SemaphoreSlim.Wait メソッドまたは SemaphoreSlim.WaitAsync メソッドから継承されます (SemaphoreSlim オブジェクトの場合)。Threads enter the semaphore by calling the WaitOne method, which is inherited from the WaitHandle class, in the case of a System.Threading.Semaphore object, or the SemaphoreSlim.Wait or SemaphoreSlim.WaitAsync method, in the case of a SemaphoreSlim object.. 呼び出しが戻されると、セマフォのカウントがデクリメントします。When the call returns, the count on the semaphore is decremented. スレッドがエントリを要求し、カウントがゼロの場合、そのスレッドはブロックされます。When a thread requests entry and the count is zero, the thread blocks. スレッドが Semaphore.Release メソッドまたは SemaphoreSlim.Release メソッドを呼び出してセマフォを解放すると、ブロックされたスレッドがセマフォに入ることができるようになります。As threads release the semaphore by calling the Semaphore.Release or SemaphoreSlim.Release method, blocked threads are allowed to enter. ブロックされたスレッドがセマフォに入る順序には、先入れ先出し (FIFO) や後入れ先出し (LIFO) などの決まった順序がありません。There is no guaranteed order, such as first-in, first-out (FIFO) or last-in, first-out (LIFO), for blocked threads to enter the semaphore.

スレッドは、System.Threading.Semaphore オブジェクトの WaitOne メソッドまたは SemaphoreSlim オブジェクトの Wait メソッドを繰り返し呼び出すことで、セマフォに複数回入ることができます。A thread can enter the semaphore multiple times by calling the System.Threading.Semaphore object's WaitOne method or the SemaphoreSlim object's Wait method repeatedly. セマフォを解放するために、スレッドは、Semaphore.Release() メソッド オーバーロードまたは SemaphoreSlim.Release() メソッド オーバーロードを同じ回数呼び出すか、Semaphore.Release(Int32) メソッド オーバーロードまたは SemaphoreSlim.Release(Int32) メソッド オーバーロードを呼び出して、解放するエントリ数を指定します。To release the semaphore, the thread can either call the Semaphore.Release() or SemaphoreSlim.Release() method overload the same number of times, or call the Semaphore.Release(Int32) or SemaphoreSlim.Release(Int32) method overload and specify the number of entries to be released.

セマフォとスレッド IDSemaphores and Thread Identity

この 2 つの種類のセマフォは、WaitOneWaitRelease、および SemaphoreSlim.Release の各メソッドの呼び出しでスレッド ID を適用しません。The two semaphore types do not enforce thread identity on calls to the WaitOne, Wait, Release, and SemaphoreSlim.Release methods. たとえば、セマフォの一般的な使用シナリオでは、producer スレッドと consumer スレッドが使用され、一方のスレッドが常にセマフォ カウントをインクリメントし、もう一方のスレッドが常にセマフォ カウントをデクリメントします。For example, a common usage scenario for semaphores involves a producer thread and a consumer thread, with one thread always incrementing the semaphore count and the other always decrementing it.

プログラマは、スレッドによるセマフォの解放回数が多くなりすぎないようにする必要があります。It is the programmer's responsibility to ensure that a thread does not release the semaphore too many times. たとえば、セマフォの最大カウントが 2 で、スレッド A とスレッド B が両方ともセマフォに入るとします。For example, suppose a semaphore has a maximum count of two, and that thread A and thread B both enter the semaphore. スレッド B がプログラミング エラーのために Release を 2 回呼び出した場合、この呼び出しは両方とも成功します。If a programming error in thread B causes it to call Release twice, both calls succeed. セマフォのカウントがいっぱいになっているときに、スレッド A も Release を呼び出すと、SemaphoreFullException がスローされます。The count on the semaphore is full, and when thread A eventually calls Release, a SemaphoreFullException is thrown.

名前付きセマフォNamed Semaphores

Windows オペレーティング システムでは、セマフォに名前を付けることができます。The Windows operating system allows semaphores to have names. 名前付きセマフォはシステム全体でのセマフォです。A named semaphore is system wide. つまり、名前付きセマフォは、作成されると、すべてのプロセスのすべてのスレッドで認識されるようになります。That is, once the named semaphore is created, it is visible to all threads in all processes. そのため、名前付きセマフォは、プロセスおよびスレッドのアクティビティを同期するために使用できます。Thus, named semaphore can be used to synchronize the activities of processes as well as threads.

名前を指定するコンストラクターのいずれかを使用して、名前付きシステム セマフォを表す Semaphore オブジェクトを作成できます。You can create a Semaphore object that represents a named system semaphore by using one of the constructors that specifies a name.

注意

名前付きセマフォはシステム全体でのセマフォであるため、同じ名前付きセマフォを表す複数の Semaphore オブジェクトが存在する可能性があります。Because named semaphores are system wide, it is possible to have multiple Semaphore objects that represent the same named semaphore. コンストラクターまたは Semaphore.OpenExisting メソッドを呼び出すたびに、新しい Semaphore オブジェクトが作成されます。Each time you call a constructor or the Semaphore.OpenExisting method, a new Semaphore object is created. 同じ名前を繰り返し指定すると、同じ名前付きセマフォを表す複数のオブジェクトが作成されます。Specifying the same name repeatedly creates multiple objects that represent the same named semaphore.

名前付きセマフォを使用する際には注意する必要があります。Be careful when you use named semaphores. システム全体でのセマフォであるため、同じ名前を使用する別のプロセスが予期せずセマフォに入る可能性があります。Because they are system wide, another process that uses the same name can enter your semaphore unexpectedly. 同じコンピューター上で実行される悪意のあるコードが、これをサービス拒否攻撃の土台として使用する可能性があります。Malicious code executing on the same computer could use this as the basis of a denial-of-service attack.

アクセス制御セキュリティを使用して、名前付きセマフォを表す Semaphore オブジェクトを保護します。可能であれば System.Security.AccessControl.SemaphoreSecurity オブジェクトを指定するコンストラクターを使用して保護します。Use access control security to protect a Semaphore object that represents a named semaphore, preferably by using a constructor that specifies a System.Security.AccessControl.SemaphoreSecurity object. Semaphore.SetAccessControl メソッドを使用してアクセス制御セキュリティを適用することもできますが、この場合、セマフォが作成されてから保護されるまでの間に無防備な時間帯が生じてしまいます。You can also apply access control security using the Semaphore.SetAccessControl method, but this leaves a window of vulnerability between the time the semaphore is created and the time it is protected. アクセス制御セキュリティによりセマフォを保護すると、悪意のある攻撃を防ぐことができますが、意図しない名前の競合の問題の解決にはなりません。Protecting semaphores with access control security helps prevent malicious attacks, but does not solve the problem of unintentional name collisions.

参照See Also

Semaphore
SemaphoreSlim
スレッド処理オブジェクトと機能Threading Objects and Features