次の方法で共有


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 回の操作で変数をインクリメントまたはデクリメントして、結果値を格納します。変数のインクリメントは、ほとんどのコンピュータでは、分割不可能な操作ではなく、次のような手順が必要となります。

  1. インスタンス変数の値をレジスタに読み込みます。
  2. 値をインクリメントまたはデクリメントします。
  3. 値をインスタンス変数に格納します。

IncrementDecrement を使用しない場合は、最初の 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