Interlocked クラス

定義

複数のスレッドによって共有される変数にアトミック操作を提供します。

public ref class Interlocked abstract sealed
public ref class Interlocked sealed
public static class Interlocked
public sealed class Interlocked
type Interlocked = class
Public Class Interlocked
Public NotInheritable Class Interlocked
継承
Interlocked

次のコード例は、スレッド セーフなリソース ロック メカニズムを示しています。

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;
};

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();

   }
}
using System;
using System.Threading;

namespace InterlockedExchange_Example
{
    class MyInterlockedExchangeExampleClass
    {
        //0 for false, 1 for true.
        private static int usingResource = 0;

        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;
            }
        }
    }
}
Imports System.Threading

Namespace InterlockedExchange_Example
    Class MyInterlockedExchangeExampleClass
        '0 for false, 1 for true.
        Private Shared usingResource As Integer = 0

        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

        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 

        '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 
    End Class 
End Namespace

注釈

このクラスのメソッドは、スレッドが他のスレッドからアクセスできる変数を更新している間、または 2 つのスレッドが別々のプロセッサで同時に実行しているときに、スケジューラがコンテキストを切り替えたときに発生する可能性があるエラーから保護するのに役立ちます。 このクラスのメンバーは例外をスローしません。

Increment メソッドと Decrement メソッドは、変数をインクリメントまたはデクリメントし、結果の値を 1 つの操作に格納します。 ほとんどのコンピューターでは、変数のインクリメントはアトミック操作ではなく、次の手順を必要とします。

  1. インスタンス変数からレジスタに値を読み込みます。

  2. 値をインクリメントまたはデクリメントします。

  3. 値をインスタンス変数に格納します。

IncrementDecrementを使用しない場合は、最初の 2 つの手順を実行した後にスレッドを割り込むことができます。 その後、別のスレッドで 3 つのステップをすべて実行できます。 最初のスレッドが実行を再開すると、インスタンス変数の値が上書きされ、2 番目のスレッドによって実行されるインクリメントまたはデクリメントの効果が失われます。

Add メソッドは、整数値を整数変数にアトミックに追加し、変数の新しい値を返します。

Exchange メソッドは、指定された変数の値をアトミックに交換します。 CompareExchange メソッドは、2 つの値を比較し、比較の結果に基づいていずれかの変数に 3 番目の値を格納する 2 つの操作を組み合わせます。 比較操作と交換操作はアトミック操作として実行されます。

共有変数への書き込みアクセスまたは読み取りアクセスがアトミックであることを確認します。 そうしないと、データが破損しているか、読み込まれた値が正しくない可能性があります。

メソッド

Add(Int32, Int32)

2 つの 32 ビット整数を追加し、最初の整数をアトミック演算として合計に置き換えます。

Add(Int64, Int64)

2 つの 64 ビット整数を追加し、最初の整数をアトミック演算として合計に置き換えます。

Add(UInt32, UInt32)

2 つの 32 ビット符号なし整数を追加し、最初の整数をアトミック演算として合計に置き換えます。

Add(UInt64, UInt64)

2 つの 64 ビット符号なし整数を追加し、最初の整数をアトミック演算として合計に置き換えます。

And(Int32, Int32)

2 つの 32 ビット符号付き整数をビットごとの "ands" し、最初の整数をアトミック演算として結果に置き換えます。

And(Int64, Int64)

2 つの 64 ビット符号付き整数をビットごとの "ands" し、最初の整数をアトミック演算として結果に置き換えます。

And(UInt32, UInt32)

2 つの 32 ビット符号なし整数をビットごとの "ands" し、最初の整数をアトミック演算として結果に置き換えます。

And(UInt64, UInt64)

2 つの 64 ビット符号なし整数をビットごとの "ands" し、最初の整数をアトミック演算として結果に置き換えます。

CompareExchange(Byte, Byte, Byte)

2 つの 8 ビット符号なし整数の等価性を比較し、等しい場合は、最初の値をアトミック演算として置き換えます。

CompareExchange(Double, Double, Double)

2 つの倍精度浮動小数点数の等価性を比較し、等しい場合は、最初の値をアトミック演算として置き換えます。

CompareExchange(Int16, Int16, Int16)

2 つの 16 ビット符号なし整数の等価性を比較し、等しい場合は、最初の値をアトミック演算として置き換えます。

CompareExchange(Int32, Int32, Int32)

2 つの 32 ビット符号付き整数の等価性を比較し、等しい場合は、最初の値をアトミック演算として置き換えます。

CompareExchange(Int64, Int64, Int64)

2 つの 64 ビット符号付き整数の等価性を比較し、等しい場合は、最初の値をアトミック演算として置き換えます。

CompareExchange(IntPtr, IntPtr, IntPtr)

2 つのプラットフォーム固有のハンドルまたはポインターが等しいかどうかを比較し、等しい場合は、最初のハンドルをアトミック操作として置き換えます。

CompareExchange(Object, Object, Object)

参照の等価性について 2 つのオブジェクトを比較し、等しい場合は、最初のオブジェクトをアトミック操作として置き換えます。

CompareExchange(SByte, SByte, SByte)

2 つの 8 ビット符号付き整数の等価性を比較し、等しい場合は、最初の値をアトミック演算として置き換えます。

CompareExchange(Single, Single, Single)

2 つの単精度浮動小数点数の等価性を比較し、等しい場合は、最初の値をアトミック演算として置き換えます。

CompareExchange(UInt16, UInt16, UInt16)

2 つの 16 ビット符号付き整数の等価性を比較し、等しい場合は、最初の値をアトミック演算として置き換えます。

CompareExchange(UInt32, UInt32, UInt32)

2 つの 32 ビット符号なし整数の等価性を比較し、等しい場合は、最初の値をアトミック演算として置き換えます。

CompareExchange(UInt64, UInt64, UInt64)

2 つの 64 ビット符号なし整数の等価性を比較し、等しい場合は、最初の値をアトミック演算として置き換えます。

CompareExchange(UIntPtr, UIntPtr, UIntPtr)

2 つのプラットフォーム固有のハンドルまたはポインターが等しいかどうかを比較し、等しい場合は、最初のハンドルをアトミック操作として置き換えます。

CompareExchange<T>(T, T, T)

指定した参照型 T の 2 つのインスタンスを参照の等価性と比較し、等しい場合は、最初のインスタンスをアトミック操作として置き換えます。

Decrement(Int32)

指定した変数をデクリメントし、結果をアトミック操作として格納します。

Decrement(Int64)

指定した変数をデクリメントし、結果をアトミック操作として格納します。

Decrement(UInt32)

指定した変数をデクリメントし、結果をアトミック操作として格納します。

Decrement(UInt64)

指定した変数をデクリメントし、結果をアトミック操作として格納します。

Exchange(Byte, Byte)

8 ビット符号なし整数を指定した値に設定し、元の値をアトミック操作として返します。

Exchange(Double, Double)

倍精度浮動小数点数を指定した値に設定し、元の値をアトミック演算として返します。

Exchange(Int16, Int16)

16 ビット符号なし整数を指定した値に設定し、元の値をアトミック操作として返します。

Exchange(Int32, Int32)

32 ビット符号付き整数を指定した値に設定し、元の値をアトミック操作として返します。

Exchange(Int64, Int64)

64 ビット符号付き整数を指定した値に設定し、元の値をアトミック操作として返します。

Exchange(IntPtr, IntPtr)

プラットフォーム固有のハンドルまたはポインターを指定した値に設定し、元の値をアトミック操作として返します。

Exchange(Object, Object)

オブジェクトを指定した値に設定し、元のオブジェクトへの参照をアトミック操作として返します。

Exchange(SByte, SByte)

8 ビット符号付き整数を指定した値に設定し、元の値をアトミック操作として返します。

Exchange(Single, Single)

単精度浮動小数点数を指定した値に設定し、アトミック演算として元の値を返します。

Exchange(UInt16, UInt16)

16 ビット符号付き整数を指定した値に設定し、元の値をアトミック操作として返します。

Exchange(UInt32, UInt32)

32 ビット符号なし整数を指定した値に設定し、元の値をアトミック操作として返します。

Exchange(UInt64, UInt64)

64 ビット符号なし整数を指定した値に設定し、元の値をアトミック操作として返します。

Exchange(UIntPtr, UIntPtr)

プラットフォーム固有のハンドルまたはポインターを指定した値に設定し、元の値をアトミック操作として返します。

Exchange<T>(T, T)

指定した型 T の変数を指定した値に設定し、元の値をアトミック操作として返します。

Increment(Int32)

指定した変数をインクリメントし、結果をアトミック操作として格納します。

Increment(Int64)

指定した変数をインクリメントし、結果をアトミック操作として格納します。

Increment(UInt32)

指定した変数をインクリメントし、結果をアトミック操作として格納します。

Increment(UInt64)

指定した変数をインクリメントし、結果をアトミック操作として格納します。

MemoryBarrier()

メモリ アクセスを次のように同期します。現在のスレッドを実行するプロセッサは、MemoryBarrier()の呼び出しに続くメモリ アクセス後に実行 MemoryBarrier() 呼び出しの前にメモリがアクセスするように命令を並べ替えることはできません。

MemoryBarrierProcessWide()

プロセス全体のメモリ バリアを提供します。これにより、CPU からの読み取りと書き込みがバリアを越えて移動できなくなります。

Or(Int32, Int32)

2 つの 32 ビット符号付き整数をビットごとの "ors" し、最初の整数をアトミック演算として結果に置き換えます。

Or(Int64, Int64)

2 つの 64 ビット符号付き整数をビットごとの "ors" し、最初の整数をアトミック演算として結果に置き換えます。

Or(UInt32, UInt32)

2 つの 32 ビット符号なし整数をビットごとの "ors" し、最初の整数をアトミック演算として結果に置き換えます。

Or(UInt64, UInt64)

2 つの 64 ビット符号なし整数をビットごとの "ors" し、最初の整数をアトミック演算として結果に置き換えます。

Read(Int64)

アトミック操作として読み込まれた 64 ビット値を返します。

Read(UInt64)

アトミック操作として読み込まれた 64 ビット符号なし値を返します。

SpeculationBarrier()

保留中の読み取りと書き込みが完了するまで、この時点を過ぎて投機的実行をブロックするメモリ フェンスを定義します。

適用対象

スレッド セーフ

この型はスレッド セーフです。

こちらもご覧ください