다음을 통해 공유


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

설명

이 클래스의 메서드는 스레드가 다른 스레드에서 액세스할 수 있는 변수를 업데이트하는 동안 또는 두 스레드가 별도의 프로세서에서 동시에 실행되는 경우 스케줄러가 컨텍스트를 전환할 때 발생할 수 있는 오류로부터 보호하는 데 도움이 됩니다. 이 클래스의 멤버는 예외를 throw하지 않습니다.

IncrementDecrement 메서드는 변수를 증가 또는 감소시키고 결과 값을 단일 작업에 저장합니다. 대부분의 컴퓨터에서 변수를 증가시키는 것은 원자성 작업이 아니며 다음 단계가 필요합니다.

  1. 인스턴스 변수의 값을 레지스터로 로드합니다.

  2. 값을 증가 또는 감소합니다.

  3. 인스턴스 변수에 값을 저장합니다.

Increment 사용하지 않고 Decrement경우 처음 두 단계를 실행한 후 스레드를 선점할 수 있습니다. 그런 다음 다른 스레드는 세 단계를 모두 실행할 수 있습니다. 첫 번째 스레드가 실행을 다시 시작하면 인스턴스 변수의 값을 덮어쓰고 두 번째 스레드에서 수행하는 증가 또는 감소의 효과는 손실됩니다.

Add 메서드는 정수 변수에 정수 값을 원자성으로 추가하고 변수의 새 값을 반환합니다.

Exchange 메서드는 지정된 변수의 값을 원자성으로 교환합니다. CompareExchange 메서드는 두 값을 비교하고 비교 결과에 따라 변수 중 하나에 세 번째 값을 저장하는 두 가지 연산을 결합합니다. 비교 및 교환 작업은 원자성 연산으로 수행됩니다.

공유 변수에 대한 쓰기 또는 읽기 액세스가 원자성인지 확인합니다. 그렇지 않으면 데이터가 손상되었거나 로드된 값이 올바르지 않을 수 있습니다.

메서드

Add(Int32, Int32)

두 개의 32비트 정수를 추가하고 첫 번째 정수를 원자성 연산으로 합계로 바꿉니다.

Add(Int64, Int64)

두 개의 64비트 정수를 추가하고 첫 번째 정수를 원자성 연산으로 합계로 바꿉니다.

Add(UInt32, UInt32)

부호 없는 32비트 정수 2개를 추가하고 첫 번째 정수를 원자성 연산으로 합계로 바꿉니다.

Add(UInt64, UInt64)

두 개의 64비트 부호 없는 정수를 추가하고 첫 번째 정수를 원자성 연산으로 합계로 바꿉니다.

And(Int32, Int32)

비트 "ands"는 두 개의 32비트 부가 정수이며 첫 번째 정수는 원자성 연산으로 결과로 바꿉니다.

And(Int64, Int64)

비트 "ands"는 두 개의 64비트 부가 정수이며 첫 번째 정수는 원자성 연산으로 결과로 바꿉니다.

And(UInt32, UInt32)

비트 "ands" 두 개의 32비트 부호 없는 정수이며 첫 번째 정수는 원자성 연산으로 결과로 바꿉니다.

And(UInt64, UInt64)

비트 "ands"는 두 개의 64비트 부호 없는 정수이며 첫 번째 정수는 원자성 연산으로 결과로 바꿉니다.

CompareExchange(Byte, Byte, Byte)

두 개의 8비트 부호 없는 정수가 같은지 비교하고, 같으면 첫 번째 값을 바꿉니다.

CompareExchange(Double, Double, Double)

두 개의 배정밀도 부동 소수점 숫자를 같음으로 비교하고 같은 경우 첫 번째 값을 바꿉니다.

CompareExchange(Int16, Int16, Int16)

두 개의 16비트 부호 없는 정수가 같은지 비교하고 같으면 첫 번째 값을 바꿉니다.

CompareExchange(Int32, Int32, Int32)

두 개의 32비트 부속 정수가 같은지 비교하고 같으면 첫 번째 값을 바꿉니다.

CompareExchange(Int64, Int64, Int64)

두 개의 64비트 부속 정수가 같은지 비교하고, 같으면 첫 번째 값을 바꿉니다.

CompareExchange(IntPtr, IntPtr, IntPtr)

두 플랫폼별 핸들 또는 포인터를 같음으로 비교하고 같은 경우 첫 번째 핸들을 바꿉니다.

CompareExchange(Object, Object, Object)

두 개체를 참조 같음으로 비교하고 같은 경우 첫 번째 개체를 바꿉니다.

CompareExchange(SByte, SByte, SByte)

두 개의 8비트 부속 정수가 같은지 비교하고, 같으면 첫 번째 값을 바꿉니다.

CompareExchange(Single, Single, Single)

두 개의 단정밀도 부동 소수점 숫자를 같음으로 비교하고 같은 경우 첫 번째 값을 바꿉니다.

CompareExchange(UInt16, UInt16, UInt16)

두 개의 16비트 부속 정수가 같은지 비교하고 같은 경우 첫 번째 값을 바꿉니다.

CompareExchange(UInt32, UInt32, UInt32)

두 개의 32비트 부호 없는 정수가 같은지 비교하고, 같으면 첫 번째 값을 바꿉니다.

CompareExchange(UInt64, UInt64, UInt64)

두 개의 64비트 부호 없는 정수가 같은지 비교하고 같으면 첫 번째 값을 바꿉니다.

CompareExchange(UIntPtr, UIntPtr, UIntPtr)

두 플랫폼별 핸들 또는 포인터를 같음으로 비교하고 같은 경우 첫 번째 핸들을 바꿉니다.

CompareExchange<T>(T, T, T)

지정된 참조 형식의 두 인스턴스를 T 참조 같음과 같은 경우 첫 번째 인스턴스를 바꿉니다.

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)

비트 "ors"는 두 개의 32비트 부가 정수이며 첫 번째 정수는 원자성 연산으로 결과로 바꿉니다.

Or(Int64, Int64)

비트 "ors"는 두 개의 64비트 부가 정수이며 첫 번째 정수는 원자성 연산으로 결과로 바꿉니다.

Or(UInt32, UInt32)

비트 "ors" 두 개의 32비트 부호 없는 정수이며 첫 번째 정수는 원자성 연산으로 결과로 바꿉니다.

Or(UInt64, UInt64)

비트 "ors" 두 개의 64비트 부호 없는 정수이며 첫 번째 정수는 원자성 연산으로 결과로 바꿉니다.

Read(Int64)

원자성 연산으로 로드된 64비트 값을 반환합니다.

Read(UInt64)

원자성 연산으로 로드된 64비트 부호 없는 값을 반환합니다.

SpeculationBarrier()

보류 중인 읽기 및 쓰기가 완료될 때까지 이 시점을 지나 투기적 실행을 차단하는 메모리 펜스를 정의합니다.

적용 대상

스레드 보안

이 형식은 스레드로부터 안전합니다.

추가 정보