Interlocked クラス
アセンブリ: mscorlib (mscorlib.dll 内)
構文
解説
このクラスのメソッドは、他のスレッドからアクセスできる変数をスレッドが更新しているとき、または 2 つのスレッドが別々のプロセッサで同時に実行されているときに、スケジューラがコンテキストの切り替えを行うと発生するエラーを防ぎます。このクラスのメンバは、例外をスローしません。
Increment メソッドと Decrement メソッドは、1 回の操作で変数をインクリメントまたはデクリメントして、結果値を格納します。変数のインクリメントは、ほとんどのコンピュータでは、分割不可能な操作ではなく、次のような手順が必要となります。
Increment と Decrement を使用しない場合は、最初の 2 つの手順を実行した後で、別のスレッドが優先処理される可能性があります。また、別のスレッドが 3 つのすべての手順を先行して完了させることもあります。最初のスレッドが実行を再開したときにインスタンス変数の値が上書きされるため、2 番目のスレッドが実行したインクリメントまたはデクリメントの結果は失われます。
Exchange メソッドは、指定した変数の値を分割不可能な方法で交換します。CompareExchange メソッドは、2 つの操作を組み合わせます。ここでは、2 つの値を比較し、その比較結果に基づいてその変数のいずれかに 3 つ目の値を格納します。比較操作および交換操作は、分割不可能な操作として実行されます。
Imports System Imports System.Threading Namespace InterlockedExchange_Example Class MyInterlockedExchangeExampleClass '0 for false, 1 for true. Private Shared usingResource As Integer = 0 Private Shared currentMso As [Object] Private Shared globalMso As New [Object]() Private Const numThreadIterations As Integer = 5 Private Const numThreads As Integer = 10 <MTAThread> _ Shared Sub Main() Dim myThread As Thread Dim rnd As New Random() Dim i As Integer For i = 0 To numThreads - 1 myThread = New Thread(AddressOf MyThreadProc) myThread.Name = [String].Format("Thread{0}", i + 1) 'Wait a random amount of time before starting next thread. Thread.Sleep(rnd.Next(0, 1000)) myThread.Start() Next i End Sub 'Main Private Shared Sub MyThreadProc() Dim i As Integer For i = 0 To numThreadIterations - 1 UseResource() 'Wait 1 second before next attempt. Thread.Sleep(1000) Next i End Sub 'MyThreadProc 'A simple method that denies reentrancy. Shared Function UseResource() As Boolean '0 indicates that the method is not in use. If 0 = Interlocked.Exchange(usingResource, 1) Then Console.WriteLine("{0} acquired the lock", Thread.CurrentThread.Name) 'Code to access a resource that is not thread safe would go here. 'Simulate some work Thread.Sleep(500) Console.WriteLine("{0} exiting lock", Thread.CurrentThread.Name) 'Release the lock Interlocked.Exchange(usingResource, 0) Return True Else Console.WriteLine(" {0} was denied the lock", Thread.CurrentThread.Name) Return False End If End Function 'UseResource End Class 'MyInterlockedExchangeExampleClass End Namespace 'InterlockedExchange_Example
using System; using System.Threading; namespace InterlockedExchange_Example { class MyInterlockedExchangeExampleClass { //0 for false, 1 for true. private static int usingResource = 0; private static Object currentMso; private static Object globalMso = new Object(); private const int numThreadIterations = 5; private const int numThreads = 10; static void Main() { Thread myThread; Random rnd = new Random(); for(int i = 0; i < numThreads; i++) { myThread = new Thread(new ThreadStart(MyThreadProc)); myThread.Name = String.Format("Thread{0}", i + 1); //Wait a random amount of time before starting next thread. Thread.Sleep(rnd.Next(0, 1000)); myThread.Start(); } } private static void MyThreadProc() { for(int i = 0; i < numThreadIterations; i++) { UseResource(); //Wait 1 second before next attempt. Thread.Sleep(1000); } } //A simple method that denies reentrancy. static bool UseResource() { //0 indicates that the method is not in use. if(0 == Interlocked.Exchange(ref usingResource, 1)) { Console.WriteLine("{0} acquired the lock", Thread.CurrentThread.Name); //Code to access a resource that is not thread safe would go here. //Simulate some work Thread.Sleep(500); Console.WriteLine("{0} exiting lock", Thread.CurrentThread.Name); //Release the lock Interlocked.Exchange(ref usingResource, 0); return true; } else { Console.WriteLine(" {0} was denied the lock", Thread.CurrentThread.Name); return false; } } } }
using namespace System; using namespace System::Threading; const int numThreads = 10; const int numThreadIterations = 5; ref class MyInterlockedExchangeExampleClass { public: static void MyThreadProc() { for ( int i = 0; i < numThreadIterations; i++ ) { UseResource(); //Wait 1 second before next attempt. Thread::Sleep( 1000 ); } } private: //A simple method that denies reentrancy. static bool UseResource() { //0 indicates that the method is not in use. if ( 0 == Interlocked::Exchange( usingResource, 1 ) ) { Console::WriteLine( " {0} acquired the lock", Thread::CurrentThread->Name ); //Code to access a resource that is not thread safe would go here. //Simulate some work Thread::Sleep( 500 ); Console::WriteLine( " {0} exiting lock", Thread::CurrentThread->Name ); //Release the lock Interlocked::Exchange( usingResource, 0 ); return true; } else { Console::WriteLine( " {0} was denied the lock", Thread::CurrentThread->Name ); return false; } } //0 for false, 1 for true. static int usingResource; static Object^ globalMso = gcnew Object; }; int main() { Thread^ myThread; Random^ rnd = gcnew Random; for ( int i = 0; i < numThreads; i++ ) { myThread = gcnew Thread( gcnew ThreadStart( MyInterlockedExchangeExampleClass::MyThreadProc ) ); myThread->Name = String::Format( "Thread {0}", i + 1 ); //Wait a random amount of time before starting next thread. Thread::Sleep( rnd->Next( 0, 1000 ) ); myThread->Start(); } }
package InterlockedExchange_Example ; import System .* ; import System.Threading .* ; import System.Threading.Thread; class MyInterlockedExchangeExampleClass { //0 for false, 1 for true. private static int usingResource = 0; private static Object currentMso; private static Object globalMso = new Object(); private static int numThreadIterations = 5; private static int numThreads = 10; public static void main(String[] args) { Thread myThread; Random rnd = new Random(); for (int i = 0; i < numThreads; i++) { myThread = new Thread(new ThreadStart(MyThreadProc)); myThread.set_Name(String.Format("Thread{0}", String.valueOf(i + 1))); //Wait a random amount of time before starting next thread. Thread.Sleep(rnd.Next(0, 1000)); myThread.Start(); } } //main private static void MyThreadProc() { for (int i = 0; i < numThreadIterations; i++) { UseResource(); //Wait 1 second before next attempt. Thread.Sleep(1000); } } //MyThreadProc //A simple method that denies reentrancy. static boolean UseResource() { //0 indicates that the method is not in use. if (0 == Interlocked.Exchange(usingResource, 1)) { Console.WriteLine("{0} acquired the lock", Thread.get_CurrentThread().get_Name()); //Code to access a resource that is not thread safe would go here. //Simulate some work Thread.Sleep(500); Console.WriteLine("{0} exiting lock", Thread.get_CurrentThread().get_Name()); //Release the lock Interlocked.Exchange(usingResource, 0); return true; } else { Console.WriteLine(" {0} was denied the lock", Thread.get_CurrentThread().get_Name()); return false; } } //UseResource } //MyInterlockedExchangeExampleClass
System.Threading.Interlocked
この型は、スレッド セーフです。
Windows 98, Windows 2000 SP4, Windows CE, Windows Millennium Edition, Windows Mobile for Pocket PC, Windows Mobile for Smartphone, Windows Server 2003, Windows XP Media Center Edition, Windows XP Professional x64 Edition, Windows XP SP2, Windows XP Starter Edition
開発プラットフォームの中には、.NET Framework によってサポートされていないバージョンがあります。サポートされているバージョンについては、「システム要件」を参照してください。
参照
- Interlocked クラスのページへのリンク