同期プリミティブの概要Overview of synchronization primitives

.NET では、共有リソースへのアクセスを同期する場合や、スレッド相互作用を調整する場合に使用できるさまざまな型が提供されます。.NET provides a range of types that you can use to synchronize access to a shared resource or coordinate thread interaction.

重要

共有リソースへのすべてのアクセスを保護するには、同じ同期プリミティブ インスタンスを使用します。Use the same synchronization primitive instance to protect every access to a shared resource. 異なる同期プリミティブ インスタンスを使用してリソースへのアクセスを保護する場合や、一部のコードでリソースに直接アクセスする場合、複数のスレッドで同時にリソースにアクセスできます。Multiple threads can access a resource concurrently if you use different synchronization primitive instances to protect access to a resource or some parts of code access a resource directly.

WaitHandle クラスと軽量の同期型WaitHandle class and lightweight synchronization types

複数の .NET 同期プリミティブは System.Threading.WaitHandle クラスから派生します。このクラスでは、ネイティブ オペレーティング システムの同期ハンドルをカプセル化し、スレッド相互作用のシグナリング メカニズムを使用します。Multiple .NET synchronization primitives derive from the System.Threading.WaitHandle class, which encapsulates a native operating system synchronization handle and uses a signaling mechanism for thread interaction. 次のようなクラスが含まれます。Those classes include:

  • System.Threading.Mutex。共有リソースへの排他アクセスが許可されます。System.Threading.Mutex, which grants exclusive access to a shared resource. 所有しているスレッドがない場合、ミューテックスはシグナル状態になります。The state of a mutex is signaled if no thread owns it.
  • System.Threading.Semaphore。共有リソースまたはリソースのプールに同時にアクセスできるスレッドの数を制限します。System.Threading.Semaphore, which limits the number of threads that can access a shared resource or a pool of resources concurrently. セマフォの状態は、そのカウントが 0 より大きい場合はシグナル状態に、0 の場合は非シグナル状態に設定されます。The state of a semaphore is set to signaled when its count is greater than zero, and nonsignaled when its count is zero.
  • System.Threading.EventWaitHandle。スレッド同期イベントを表し、シグナル状態または非シグナル状態のいずれかになります。System.Threading.EventWaitHandle, which represents a thread synchronization event and can be either in a signaled or unsignaled state.
  • System.Threading.AutoResetEventEventWaitHandle から派生し、シグナル状態の場合、単一の待ちスレッドを解放した後、自動的に非シグナル状態にリセットされます。System.Threading.AutoResetEvent, which derives from EventWaitHandle and, when signaled, resets automatically to an unsignaled state after releasing a single waiting thread.
  • System.Threading.ManualResetEventEventWaitHandle から派生し、シグナル状態の場合、Reset メソッドが呼び出されるまでシグナル状態のままです。System.Threading.ManualResetEvent, which derives from EventWaitHandle and, when signaled, stays in a signaled state until the Reset method is called.

.NET Framework では、WaitHandleSystem.MarshalByRefObject から派生するため、これらの型を使用して、アプリケーション ドメインの境界を越えてスレッドのアクティビティを同期させることができます。In the .NET Framework, because WaitHandle derives from System.MarshalByRefObject, these types can be used to synchronize the activities of threads across application domain boundaries.

.NET Framework と .NET Core では、これらの型のいくつかで名前付きのシステム同期ハンドルを表すことができます。ハンドルはオペレーティング システム全体で表示され、プロセス間同期で使用できます。In the .NET Framework and .NET Core, some of these types can represent named system synchronization handles, which are visible throughout the operating system and can be used for the inter-process synchronization:

  • Mutex (.NET Framework と .NET Core)、Mutex (.NET Framework and .NET Core),
  • Semaphore (Windows 上の .NET Framework と .NET Core)、Semaphore (.NET Framework and .NET Core on Windows),
  • EventWaitHandle (Windows 上の .NET Framework と .NET Core)。EventWaitHandle (.NET Framework and .NET Core on Windows).

詳細については、WaitHandle API リファレンスを参照してください。For more information, see the WaitHandle API reference.

軽量の同期型は、基になるオペレーティング システム ハンドルに依存しておらず、通常はパフォーマンスが向上します。Lightweight synchronization types don't rely on underlying operating system handles and typically provide better performance. しかし、プロセス間同期には使用できません。However, they cannot be used for the inter-process synchronization. これらの型は、1 つのアプリケーション内のスレッド同期で使用します。Use those types for thread synchronization within one application.

これらの型のいくつかは、WaitHandle から派生した型の代わりに使用できます。Some of those types are alternatives to the types derived from WaitHandle. たとえば、SemaphoreSlim は軽量であり、Semaphore の代わりに使用できます。For example, SemaphoreSlim is a lightweight alternative to Semaphore.

共有リソースへのアクセスの同期Synchronization of access to a shared resource

.NET では、複数のスレッドによる共有リソースへのアクセスを制御するためのさまざまな同期プリミティブが提供されます。.NET provides a range of synchronization primitives to control access to a shared resource by multiple threads.

Monitor クラスMonitor class

System.Threading.Monitor クラスでは、リソースを識別するオブジェクトに対するロックを取得または解放することで、共有リソースへの排他アクセスを許可します。The System.Threading.Monitor class grants mutually exclusive access to a shared resource by acquiring or releasing a lock on the object that identifies the resource. ロックが保持されている間、ロックを保持するスレッドではロックを再度取得し、解放することができます。While a lock is held, the thread that holds the lock can again acquire and release the lock. 他のスレッドはブロックされてロックを取得できず、Monitor.Enter メソッドではロックが解放されるまで待機します。Any other thread is blocked from acquiring the lock and the Monitor.Enter method waits until the lock is released. Enter メソッドでは解放されたロックを取得します。The Enter method acquires a released lock. また、Monitor.TryEnter メソッドを使用して、スレッドでのロック取得の試行時間を指定することもできます。You can also use the Monitor.TryEnter method to specify the amount of time during which a thread attempts to acquire a lock. Monitor クラスにはスレッド アフィニティがあるため、ロックを取得したスレッドでは、Monitor.Exit メソッドを呼び出してロックを解放する必要があります。Because the Monitor class has thread affinity, the thread that acquired a lock must release the lock by calling the Monitor.Exit method.

Monitor.WaitMonitor.Pulse、および Monitor.PulseAll メソッドを使用して、同じオブジェクトに対するロックを取得するスレッドの相互作用を調整することができます。You can coordinate the interaction of threads that acquire a lock on the same object by using the Monitor.Wait, Monitor.Pulse, and Monitor.PulseAll methods.

詳細については、Monitor API リファレンスを参照してください。For more information, see the Monitor API reference.

注意

C# では lock ステートメントを、Visual Basic では SyncLock ステートメントを使って、Monitor クラスを直接使用せずに、共有リソースへのアクセスを同期します。Use the lock statement in C# and the SyncLock statement in Visual Basic to synchronize access to a shared resource instead of using the Monitor class directly. これらのステートメントは、Enter および Exit メソッドを使用して実装されます。また、このステートメントでは、取得されたロックが常に確実に解除されるように、try…finally ブロックが使用されます。Those statements are implemented by using the Enter and Exit methods and a try…finally block to ensure that the acquired lock is always released.

Mutex クラスMutex class

System.Threading.Mutex クラスでは、Monitor と同様に、共有リソースへの排他アクセスを許可します。The System.Threading.Mutex class, like Monitor, grants exclusive access to a shared resource. Mutex.WaitOne メソッドのオーバーロードのいずれかを使用して、ミューテックスの所有権を要求します。Use one of the Mutex.WaitOne method overloads to request the ownership of a mutex. Monitor と同様に、Mutex にはスレッド アフィニティがあり、ミューテックスを取得したスレッドで、Mutex.ReleaseMutex メソッドを呼び出してそれを解放する必要があります。Like Monitor, Mutex has thread affinity and the thread that acquired a mutex must release it by calling the Mutex.ReleaseMutex method.

Monitor とは異なり、Mutex クラスをプロセス間同期に使用することができます。Unlike Monitor, the Mutex class can be used for inter-process synchronization. そのためには、オペレーティング システム全体で表示される、名前付きミューテックスを使用します。To do that, use a named mutex, which is visible throughout the operating system. 名前付きミュー テックスのインスタンスを作成するには、名前を指定する Mutex コンストラクターを使用します。To create a named mutex instance, use a Mutex constructor that specifies a name. また、Mutex.OpenExisting メソッドを呼び出して、既存の名前付きシステム ミューテックスを開くこともできます。You also can call the Mutex.OpenExisting method to open an existing named system mutex.

詳細については、「ミューテックス」の記事と、Mutex API リファレンスを参照してください。For more information, see the Mutexes article and the Mutex API reference.

SpinLock 構造体SpinLock structure

System.Threading.SpinLock 構造体では、Monitor と同様に、ロックの可用性に基づいて、共有リソースへの排他アクセスを許可します。The System.Threading.SpinLock structure, like Monitor, grants exclusive access to a shared resource based on the availability of a lock. SpinLock で使用できないロックの取得が試行された場合、ループ内で待機し、ロックが使用できるようになるまで繰り返し確認されます。When SpinLock attempts to acquire a lock that is unavailable, it waits in a loop, repeatedly checking until the lock becomes available.

スピン ロックを使用する利点と欠点の詳細については、「SpinLock」の記事と、SpinLock API リファレンスを参照してください。For more information about the benefits and drawbacks of using spin lock, see the SpinLock article and the SpinLock API reference.

ReaderWriterLockSlim クラスReaderWriterLockSlim class

System.Threading.ReaderWriterLockSlim クラスでは、書き込み用の共有リソースへの排他アクセスを許可し、複数のスレッドでの読み取り用のリソースへの同時アクセスを許可します。The System.Threading.ReaderWriterLockSlim class grants exclusive access to a shared resource for writing and allows multiple threads to access the resource simultaneously for reading. スレッドセーフ読み取り操作をサポートするが、書き込み操作を行うために排他アクセスを必要とする共有データ構造体へのアクセスを同期する場合は、ReaderWriterLockSlim を使用できます。You might want to use ReaderWriterLockSlim to synchronize access to a shared data structure that supports thread-safe read operations, but requires exclusive access to perform write operation. スレッドで (たとえば、ReaderWriterLockSlim.EnterWriteLock メソッドを呼び出して) 排他アクセスを要求すると、後続のリーダーとライターの要求は、既存のすべてのリーダーがロックを終了し、ライターがロックに参加して終了するまでブロックされます。When a thread requests exclusive access (for example, by calling the ReaderWriterLockSlim.EnterWriteLock method), subsequent reader and writer requests block until all existing readers have exited the lock, and the writer has entered and exited the lock.

詳細については、ReaderWriterLockSlim API リファレンスを参照してください。For more information, see the ReaderWriterLockSlim API reference.

Semaphore および SemaphoreSlim クラスSemaphore and SemaphoreSlim classes

System.Threading.Semaphore および System.Threading.SemaphoreSlim クラスでは、共有リソースまたはリソースのプールに同時にアクセスできるスレッドの数を制限します。The System.Threading.Semaphore and System.Threading.SemaphoreSlim classes limit the number of threads that can access a shared resource or a pool of resources concurrently. リソースを要求する追加のスレッドは、任意のスレッドでセマフォが解放されるまで待機します。Additional threads that request the resource wait until any thread releases the semaphore. セマフォにはスレッド アフィニティがないため、あるスレッドでセマフォを取得し、別のスレッドで解放することができます。Because the semaphore doesn't have thread affinity, a thread can acquire the semaphore and another one can release it.

SemaphoreSlim は軽量であり、Semaphore の代わりに使用され、単一のプロセス境界内の同期化でのみ使用できます。SemaphoreSlim is a lightweight alternative to Semaphore and can be used only for synchronization within a single process boundary.

Windows では、プロセス間同期で Semaphore を使用できます。On Windows, you can use Semaphore for the inter-process synchronization. そのためには、名前または Semaphore.OpenExisting メソッドを指定する Semaphore コンストラクターのいずれかを使用して、名前付きシステム セマフォを表す Semaphore インスタンスを作成します。To do that, create a Semaphore instance that represents a named system semaphore by using one of the Semaphore constructors that specifies a name or the Semaphore.OpenExisting method. SemaphoreSlim では、名前付きシステム セマフォはサポートされていません。SemaphoreSlim doesn't support named system semaphores.

詳細については、「Semaphore と SemaphoreSlim」の記事と、Semaphore または SemaphoreSlim API リファレンスを参照してください。For more information, see the Semaphore and SemaphoreSlim article and the Semaphore or SemaphoreSlim API reference.

スレッドの相互作用、またはシグナリングThread interaction, or signaling

スレッドの相互作用 (またはスレッドのシグナリング) は、あるスレッドで、先に進むために 1 つ以上のスレッドからの通知 (または、シグナル) を待機する必要があることを意味します。Thread interaction (or thread signaling) means that a thread must wait for notification, or a signal, from one or more threads in order to proceed. たとえば、スレッド A でスレッド B のThread.Join メソッドを呼び出す場合、スレッド A は、スレッド B が完了するまでブロックされます。For example, if thread A calls the Thread.Join method of thread B, thread A is blocked until thread B completes. 前のセクションで説明されている同期プリミティブでは、シグナリングに関する別のメカニズムが提供されます。その場合、あるスレッドによって、ロックを獲得することで先に進むことができる別のスレッドに通知されます。The synchronization primitives described in the preceding section provide a different mechanism for signaling: by releasing a lock, a thread notifies another thread that it can proceed by acquiring the lock.

このセクションでは、.NET によって提供される追加のシグナリング構造について説明します。This section describes additional signaling constructs provided by .NET.

EventWaitHandle、AutoResetEvent、ManualResetEvent、および ManualResetEventSlim クラスEventWaitHandle, AutoResetEvent, ManualResetEvent, and ManualResetEventSlim classes

System.Threading.EventWaitHandle クラスはスレッドの同期イベントを表します。The System.Threading.EventWaitHandle class represents a thread synchronization event.

同期イベントには、非シグナル状態またはシグナル状態のいずれかを指定できます。A synchronization event can be either in an unsignaled or signaled state. イベントの状態が非シグナルの場合、イベントの WaitOne オーバーロードを呼び出すスレッドは、イベントがシグナル状態になるまでブロックされます。When the state of an event is unsignaled, a thread that calls the event's WaitOne overload is blocked until an event is signaled. EventWaitHandle.Set メソッドでは、イベントの状態をシグナル状態に設定します。The EventWaitHandle.Set method sets the state of an event to signaled.

シグナル状態になった EventWaitHandle の動作は、そのリセット モードによって異なります。The behavior of an EventWaitHandle that has been signaled depends on its reset mode:

Windows では、プロセス間同期で EventWaitHandle を使用できます。On Windows, you can use EventWaitHandle for the inter-process synchronization. そのためには、名前または EventWaitHandle.OpenExisting メソッドを指定する EventWaitHandle コンストラクターのいずれかを使用して、名前付きシステム同期イベントを表す EventWaitHandle インスタンスを作成します。To do that, create a EventWaitHandle instance that represents a named system synchronization event by using one of the EventWaitHandle constructors that specifies a name or the EventWaitHandle.OpenExisting method.

詳細については、「EventWaitHandle」の記事を参照してください。For more information, see the EventWaitHandle article. API リファレンスについては、EventWaitHandleAutoResetEventManualResetEvent、および ManualResetEventSlim に関する記述を参照してください。For the API reference, see EventWaitHandle, AutoResetEvent, ManualResetEvent, and ManualResetEventSlim.

CountdownEvent クラスCountdownEvent class

System.Threading.CountdownEvent クラスは、そのカウントが 0 になると設定されるようになるイベントを表します。The System.Threading.CountdownEvent class represents an event that becomes set when its count is zero. CountdownEvent.CurrentCount が 0 より大きい間は、CountdownEvent.Wait を呼び出すスレッドがブロックされます。While CountdownEvent.CurrentCount is greater than zero, a thread that calls CountdownEvent.Wait is blocked. イベントのカウントをデクリメントするには、CountdownEvent.Signal を呼び出します。Call CountdownEvent.Signal to decrement an event's count.

1 つのスレッドからのシグナルで複数のスレッドのブロックを解除するために使用できる、ManualResetEventManualResetEventSlim とは対照的に、CountdownEvent を使用すると、複数のスレッドからのシグナルで 1 つ以上のスレッドのブロックを解除できます。In contrast to ManualResetEvent or ManualResetEventSlim, which you can use to unblock multiple threads with a signal from one thread, you can use CountdownEvent to unblock one or more threads with signals from multiple threads.

詳細については、「CountdownEvent」の記事と、CountdownEvent API リファレンスを参照してください。For more information, see the CountdownEvent article and the CountdownEvent API reference.

Barrier クラスBarrier class

System.Threading.Barrier クラスはスレッド実行のバリアを表します。The System.Threading.Barrier class represents a thread execution barrier. Barrier.SignalAndWait メソッドを呼び出すスレッドでは、バリアに到達したことを知らせ、他の参加スレッドがバリアに到達するまで待機します。A thread that calls the Barrier.SignalAndWait method signals that it reached the barrier and waits until other participant threads reach the barrier. すべての参加スレッドは、バリアに到達したときに先に進み、バリアはリセットされて再度使用することができます。When all participant threads reach the barrier, they proceed and the barrier is reset and can be used again.

1 つ以上のスレッドが次の計算フェーズに進む前に、他のスレッドの結果を必要とする場合は、Barrier を使用できます。You might use Barrier when one or more threads require the results of other threads before proceeding to the next computation phase.

詳細については、「バリア」の記事と、Barrier API リファレンスを参照してください。For more information, see the Barrier article and the Barrier API reference.

Interlocked クラスInterlocked class

System.Threading.Interlocked クラスでは、変数に対してシンプルなアトミック操作を実行する静的メソッドが提供されます。The System.Threading.Interlocked class provides static methods that perform simple atomic operations on a variable. それらのアトミック操作としては、64 ビット整数値を対象とした追加、インクリメントとデクリメント、交換、比較による条件付き交換、読み取りの各操作があります。Those atomic operations include addition, increment and decrement, exchange and conditional exchange that depends on a comparison, and read operation of a 64-bit integer value.

詳細については、Interlocked API リファレンスを参照してください。For more information, see the Interlocked API reference.

SpinWait 構造体SpinWait structure

System.Threading.SpinWait 構造体では、スピンベースの待機のサポートが提供されます。The System.Threading.SpinWait structure provides support for spin-based waiting. これは、イベントが通知されるか条件が満たされるのをスレッドが待機する必要があるが、待機ハンドルを使用するかあるいはスレッドをブロックする際に必要な待機時間よりも実際の待機時間が短いと思われる場合に使用できます。You might want to use it when a thread has to wait for an event to be signaled or a condition to be met, but when the actual wait time is expected to be less than the waiting time required by using a wait handle or by otherwise blocking the thread. SpinWait を使用することにより、待機中はスピンし、指定した時間内に条件が満たされなかった場合のみ (たとえば待機またはスリープして) 譲渡するための短い時間を指定できます。By using SpinWait, you can specify a short period of time to spin while waiting, and then yield (for example, by waiting or sleeping) only if the condition was not met in the specified time.

詳細については、「SpinWait」の記事と、SpinWait API リファレンスを参照してください。For more information, see the SpinWait article and the SpinWait API reference.

関連項目See also