Interlocked クラス
複数のスレッドで共有される変数に分割不可能な操作を提供します。
この型のすべてのメンバの一覧については、Interlocked メンバ を参照してください。
System.Object
System.Threading.Interlocked
NotInheritable Public Class Interlocked
[C#]
public sealed class Interlocked
[C++]
public __gc __sealed class Interlocked
[JScript]
public class Interlocked
スレッドセーフ
この型は、マルチスレッド操作に対して安全です。
解説
このクラスのメソッドは、他のスレッドからアクセスできる変数をスレッドが更新しているとき、または 2 つのスレッドが別々のプロセッサで同時に実行されているときに、スケジューラがコンテキストの切り替えを行うと発生するエラーを防ぎます。このクラスのメンバは、例外をスローしません。
Increment メソッドと Decrement メソッドは、1 回の操作で変数をインクリメントまたはデクリメントして、結果値を格納します。変数のインクリメントは、ほとんどのコンピュータでは、分割不可能な操作ではなく、次のような手順が必要となります。
- インスタンス変数の値をレジスタに読み込みます。
- 値をインクリメントまたはデクリメントします。
- 値をインスタンス変数に格納します。
Increment と Decrement を使用しない場合は、最初の 2 つの手順を実行した後で、別のスレッドが優先処理される可能性があります。また、別のスレッドが 3 つのすべての手順を先行して完了させることもあります。最初のスレッドが実行を再開したときにインスタンス変数の値が上書きされるため、2 番目のスレッドが実行したインクリメントまたはデクリメントの結果は失われます。
Exchange メソッドは、指定した変数の値を分割不可能な方法で交換します。 CompareExchange メソッドは、2 つの操作を組み合わせます。ここでは、2 つの値を比較し、その比較結果に基づいてその変数のいずれかに 3 つ目の値を格納します。比較操作および交換操作は、分割不可能な操作として実行されます。
使用例
[Visual Basic, C#, C++] スレッド セーフなリソース ロック機構の例を次に示します。
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
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
[C#]
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;
}
}
}
}
[C++]
#using <mscorlib.dll>
using namespace System;
using namespace System::Threading;
const int numThreads = 10;
const int numThreadIterations = 5;
__gc 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(S" {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(S" {0} exiting lock", Thread::CurrentThread->Name);
//Release the lock
Interlocked::Exchange( &usingResource, 0);
return true;
}
else
{
Console::WriteLine(S" {0} was denied the lock", Thread::CurrentThread->Name);
return false;
}
}
private:
//0 for false, 1 for true.
static int usingResource;
static Object* globalMso = new Object();
};
void main()
{
Thread* myThread;
Random* rnd = new Random();
for (int i = 0; i < numThreads; i++)
{
myThread = new Thread(new ThreadStart(0, MyInterlockedExchangeExampleClass::MyThreadProc));
myThread->Name = String::Format(S"Thread {0}", __box(i + 1));
//Wait a random amount of time before starting next thread.
Thread::Sleep(rnd->Next(0, 1000));
myThread->Start();
}
}
[JScript] JScript のサンプルはありません。Visual Basic、C#、および C++ のサンプルを表示するには、このページの左上隅にある言語のフィルタ ボタン をクリックします。
必要条件
名前空間: System.Threading
プラットフォーム: Windows 98, Windows NT 4.0, Windows Millennium Edition, Windows 2000, Windows XP Home Edition, Windows XP Professional, Windows Server 2003 ファミリ, .NET Compact Framework - Windows CE .NET
アセンブリ: Mscorlib (Mscorlib.dll 内)
参照
Interlocked メンバ | System.Threading 名前空間 | スレッド処理 | Interlocked