マルチスレッド処理のためのデータの同期Synchronizing data for multithreading

複数のスレッドが同じオブジェクトのプロパティとメソッドを呼び出す場合は、これらの呼び出しを同期することが重要です。When multiple threads can make calls to the properties and methods of a single object, it is critical that those calls be synchronized. 同期しないと、1 つのスレッドが行っていることを別のスレッドが中断し、オブジェクトが無効な状態になってしまう可能性があります。Otherwise one thread might interrupt what another thread is doing, and the object could be left in an invalid state. メンバーがこのように中断されないように保護されているクラスを、スレッドセーフと呼びます。A class whose members are protected from such interruptions is called thread-safe.

.NET には、インスタンスや静的メンバーへのアクセスを同期するためのいくつかの方法が用意されています。.NET provides several strategies to synchronize access to instance and static members:

  • 同期されたコード領域。Synchronized code regions. Monitor クラス、またはこのクラスに対するコンパイラ サポートを使用して、パフォーマンスを向上させながら、同期を必要とするコード ブロックだけを同期できます。You can use the Monitor class or compiler support for this class to synchronize only the code block that needs it, improving performance.

  • 手動での同期。Manual synchronization. .NET クラス ライブラリによって提供されている同期オブジェクトを使用できます。You can use the synchronization objects provided by the .NET class library. 同期プリミティブの概要」を参照してください。これには、Monitor クラスの説明が含まれています。See Overview of Synchronization Primitives, which includes a discussion of the Monitor class.

  • 同期されたコンテキスト。Synchronized contexts. .NET Framework および Xamarin アプリケーションでは、SynchronizationAttribute を使用することで、ContextBoundObject オブジェクトの単純な自動同期を有効にすることができます。For .NET Framework and Xamarin applications, you can use the SynchronizationAttribute to enable simple, automatic synchronization for ContextBoundObject objects.

  • System.Collections.Concurrent 名前空間のコレクション クラス。Collection classes in the System.Collections.Concurrent namespace. これらのクラスには、同期された追加操作および削除操作が組み込まれています。These classes provide built-in synchronized add and remove operations. 詳しくは、「スレッド セーフなコレクション」を参照してください。For more information, see Thread-Safe Collections.

共通言語ランタイムにはスレッド モデルが用意されていて、要件に応じたさまざまな方法で同期することができる多数のカテゴリにクラスを分類できます。The common language runtime provides a thread model in which classes fall into a number of categories that can be synchronized in a variety of different ways depending on the requirements. 次の表に、各同期カテゴリで提供されるフィールドおよびメソッドに対する同期サポートを示します。The following table shows what synchronization support is provided for fields and methods with a given synchronization category.

カテゴリCategory グローバル フィールドGlobal fields 静的フィールドStatic fields 静的メソッドStatic methods インスタンス フィールドInstance fields インスタンス メソッドInstance methods 特定のコード ブロックSpecific code blocks
同期なしNo Synchronization いいえNo ×No ×No ×No ×No いいえNo
同期されたコンテキストSynchronized Context いいえNo ×No ×No [はい]Yes はいYes いいえNo
同期されたコード領域Synchronized Code Regions いいえNo いいえNo マークされている場合にのみOnly if marked いいえNo マークされている場合にのみOnly if marked マークされている場合にのみOnly if marked
手動での同期Manual Synchronization 手動Manual 手動Manual 手動Manual 手動Manual 手動Manual 手動Manual

同期なしNo synchronization

これは、オブジェクトに対する既定の設定です。This is the default for objects. すべてのスレッドが、すべてのメソッドまたはフィールドにいつでもアクセスできます。Any thread can access any method or field at any time. ただし、これらのオブジェクトにアクセスできるスレッドは一度に 1 つだけです。Only one thread at a time should access these objects.

手動での同期Manual synchronization

.NET クラス ライブラリには、スレッドを同期するための多数のクラスがあります。The .NET class library provides a number of classes for synchronizing threads. 同期プリミティブの概要」を参照してください。See Overview of Synchronization Primitives.

同期されたコード領域Synchronized code regions

Monitor クラスまたはコンパイラ キーワードを使用して、コード ブロック、インスタンス メソッド、静的メソッドを同期できます。You can use the Monitor class or a compiler keyword to synchronize blocks of code, instance methods, and static methods. 同期された静的フィールドに対するサポートはありません。There is no support for synchronized static fields.

Visual Basic と C# の両方が、コード ブロックに特定の言語キーワード (C# の lock ステートメント、Visual Basic の SyncLock ステートメント) のマークを付けることをサポートしています。Both Visual Basic and C# support the marking of blocks of code with a particular language keyword, the lock statement in C# or the SyncLock statement in Visual Basic. スレッドによってコードが実行されると、ロックの取得が試行されます。When the code is executed by a thread, an attempt is made to acquire the lock. 別のスレッドによってロックが既に取得されている場合、ロックが使用可能になるまでスレッドはブロックされます。If the lock has already been acquired by another thread, the thread blocks until the lock becomes available. 同期されているコード ブロック部分の実行をスレッドが終了すると、終了方法に関係なく、ロックが解放されます。When the thread exits the synchronized block of code, the lock is released, no matter how the thread exits the block.

注意

lock ステートメントおよび SyncLock ステートメントは、Monitor.Enter および Monitor.Exit を使用して実装されるため、Monitor の他のメソッドを、同期された領域内でこれらと組み合わせて使用できます。The lock and SyncLock statements are implemented using Monitor.Enter and Monitor.Exit, so other methods of Monitor can be used in conjunction with them within the synchronized region.

また、MethodImplAttributeMethodImplOptions.Synchronized の値で使用してメソッドを修飾することもできます。これにより、Monitor またはメソッド全体をロックするためのコンパイラ キーワードの 1 つを使用した場合と同じ結果になります。You can also decorate a method with a MethodImplAttribute with a value of MethodImplOptions.Synchronized, which has the same effect as using Monitor or one of the compiler keywords to lock the entire body of the method.

Thread.Interrupt を使用すると、同期されたコード領域へのアクセスの待機などのブロック操作から、スレッドを切り離すことができます。Thread.Interrupt can be used to break a thread out of blocking operations such as waiting for access to a synchronized region of code. また、この Thread.Interrupt を使用することで、Thread.Sleep などの操作からスレッドを切り離すこともできます。Thread.Interrupt is also used to break threads out of operations like Thread.Sleep.

重要

static メソッド (Visual Basic ではShared) を保護するために、型 (C# の場合はtypeof(MyType)、Visual Basic の場合はGetType(MyType)、C++ の場合はMyType::typeid) をロックしないでください。Do not lock the type — that is, typeof(MyType) in C#, GetType(MyType) in Visual Basic, or MyType::typeid in C++ — in order to protect static methods (Shared methods in Visual Basic). 代わりにプライベート静的オブジェクトを使用します。Use a private static object instead. 同様に、C# の this (Visual Basic の場合は Me) を使用してインスタンス メソッドをロックしないでください。Similarly, do not use this in C# (Me in Visual Basic) to lock instance methods. 代わりにプライベート オブジェクトを使用します。Use a private object instead. クラスやインスタンスは、独自のコード以外のコードでもロックできますが、デッドロックやパフォーマンスの問題が発生する可能性があります。A class or instance can be locked by code other than your own, potentially causing deadlocks or performance problems.

コンパイラ サポートCompiler support

Visual Basic と C# は、どちらも Monitor.EnterMonitor.Exit を使用してオブジェクトをロックする言語キーワードをサポートします。Both Visual Basic and C# support a language keyword that uses Monitor.Enter and Monitor.Exit to lock the object. Visual Basic は SyncLock ステートメントをサポートしており、C# は lock ステートメントをサポートしています。Visual Basic supports the SyncLock statement; C# supports the lock statement.

両方とも、コード ブロックで例外がスローされると、lock または SyncLock によって取得されたロックは自動的に解放されます。In both cases, if an exception is thrown in the code block, the lock acquired by the lock or SyncLock is released automatically. C# コンパイラおよび Visual Basic コンパイラは try/finally ブロックを生成します。tryブロックは先頭に Monitor.Enter を含み、finally ブロックは Monitor.Exit を含みます。The C# and Visual Basic compilers emit a try/finally block with Monitor.Enter at the beginning of the try, and Monitor.Exit in the finally block. lock ブロックまたは SyncLock ブロック内部で例外がスローされると、finally ハンドラーが実行され、任意のクリーンアップ作業を行えるようになります。If an exception is thrown inside the lock or SyncLock block, the finally handler runs to allow you to do any clean-up work.

同期されたコンテキストSynchronized Context

.NET Framework と Xamarin のアプリケーションでのみ、任意の ContextBoundObjectSynchronizationAttribute を使用して、すべてのインスタンス メソッドとフィールドを同期できます。In .NET Framework and Xamarin applications only, you can use the SynchronizationAttribute on any ContextBoundObject to synchronize all instance methods and fields. 同じコンテキスト ドメイン内のすべてのオブジェクトが同じロックを共有します。All objects in the same context domain share the same lock. 複数のスレッドがメソッドやフィールドにアクセスできますが、これらのオブジェクトに一度にアクセスできるのは 1 つのスレッドだけです。Multiple threads are allowed to access the methods and fields, but only a single thread is allowed at any one time.

関連項目See also