Interlocked 類別

定義

為多重執行緒共用的變數提供不可部分完成的作業 (Atomic Operation)。

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

備註

這個類別的方法有助於防止排程器線上程更新可由其他執行緒存取的變數時,或當兩個執行緒同時在個別處理器上執行時,可能會發生的錯誤。 這個類別的成員不會擲回例外狀況。

IncrementDecrement 方法會遞增或遞減變數,並將產生的值儲存在單一作業中。 在大部分電腦上,遞增變數不是不可部分完成的作業,需要下列步驟:

  1. 將執行個體變數的值載入暫存器。

  2. 遞增或遞減值。

  3. 將值儲存在執行個體變數中。

如果您不使用 IncrementDecrement ,可以在執行前兩個步驟之後先占執行緒。 接著,另一個執行緒可以執行這三個步驟。 當第一個執行緒繼續執行時,它會覆寫執行個體變數中的值,並遺失第二個執行緒所執行的遞增或遞減效果。

方法 Add 會不可部分完成地將整數值新增至整數變數,並傳回變數的新值。

方法 Exchange 會以不可部分完成的方式交換指定變數的值。 方法 CompareExchange 結合兩個作業:比較兩個值,並根據比較的結果,將第三個值儲存在其中一個變數中。 比較和交換作業會以不可部分完成的作業執行。

確定共用變數的任何寫入或讀取權限都是不可部分完成的。 否則,資料可能會損毀,或載入的值可能不正確。

方法

Add(Int32, Int32)

將兩個 32 位元整數加相,並以總和取代第一個整數,成為不可部分完成的作業。

Add(Int64, Int64)

將兩個 64 位元整數加相,並以總和取代第一個整數,成為不可部分完成的作業。

Add(UInt32, UInt32)

將兩個 32 位元不帶正負號的整數相加,並以總和取代第一個整數,成為不可部分完成的作業。

Add(UInt64, UInt64)

將兩個 64 位元不帶正負號的整數相加,並以總和取代第一個整數,成為不可部分完成的作業。

And(Int32, Int32)

對兩個 32 位元帶正負號的整數進行位元「AND」運算,並以結果取代第一個整數,成為不可部分完成的作業。

And(Int64, Int64)

對兩個 64 位元帶正負號的整數進行位元「AND」運算,並以結果取代第一個整數,成為不可部分完成的作業。

And(UInt32, UInt32)

對兩個 32 位元不帶正負號的整數進行位元「AND」運算,並以結果取代第一個整數,成為不可部分完成的作業。

And(UInt64, UInt64)

對兩個 64 位元不帶正負號的整數進行位元「AND」運算,並以結果取代第一個整數,成為不可部分完成的作業。

CompareExchange(Double, Double, Double)

比較兩個雙精確度浮點數是否相等;如果相等,則取代第一個值。

CompareExchange(Int32, Int32, Int32)

比較兩個 32 位元帶正負號的整數是否相等,如果相等,則取代第一個值。

CompareExchange(Int64, Int64, Int64)

比較兩個 64 位元帶正負號的整數是否相等,如果相等,則取代第一個值。

CompareExchange(IntPtr, IntPtr, IntPtr)

比較兩個平台特定的控制代碼或指標是否相等;如果相等,則取代第一個。

CompareExchange(Object, Object, Object)

比較兩個物件的參考是否相等;如果相等,則取代第一個物件。

CompareExchange(Single, Single, Single)

比較兩個單精確度浮點數是否相等;如果相等,則取代第一個值。

CompareExchange(UInt32, UInt32, UInt32)

比較兩個 32 位元不帶正負號的整數是否相等,如果相等,則取代第一個值。

CompareExchange(UInt64, UInt64, UInt64)

比較兩個 64 位元不帶正負號的整數是否相等,如果相等,則取代第一個值。

CompareExchange<T>(T, T, T)

比較指定參考型別 T 的兩個執行個體是否參考相等;如果相等,則取代第一個。

Decrement(Int32)

遞減特定變數並將結果儲存起來,成為不可部分完成的作業。

Decrement(Int64)

遞減特定變數並將結果儲存起來,成為不可部分完成的作業。

Decrement(UInt32)

遞減特定變數並將結果儲存起來,成為不可部分完成的作業。

Decrement(UInt64)

遞減特定變數並將結果儲存起來,成為不可部分完成的作業。

Exchange(Double, Double)

將雙精確度浮點數設定為指定值,然後傳回原始值,成為不可部分完成的作業。

Exchange(Int32, Int32)

將 32 位元帶正負號的整數設定為指定值,然後傳回原始值,成為不可部分完成的作業。

Exchange(Int64, Int64)

將 64 位元帶正負號的整數設定為指定值,然後傳回原始值,成為不可部分完成的作業。

Exchange(IntPtr, IntPtr)

將平台特定的控制代碼或指標設定為指定值,然後傳回原始值,成為不可部分完成的作業。

Exchange(Object, Object)

將物件設定為指定值,然後傳回原始物件的參考,成為不可部分完成的作業。

Exchange(Single, Single)

將單精確度浮點數設定為指定值,然後傳回原始值,成為不可部分完成的作業。

Exchange(UInt32, UInt32)

將 32 位元不帶正負號的整數設定為指定值,然後傳回原始值,成為不可部分完成的作業。

Exchange(UInt64, UInt64)

將 64 位元不帶正負號的整數設定為指定值,然後傳回原始值,成為不可部分完成的作業。

Exchange<T>(T, T)

將指定類型 T 的變數設定為指定值,然後傳回原始值,成為不可部分完成的作業。

Increment(Int32)

遞增特定變數並將結果儲存起來,成為不可部分完成的作業。

Increment(Int64)

遞增特定變數並將結果儲存起來,成為不可部分完成的作業。

Increment(UInt32)

遞增特定變數並將結果儲存起來,成為不可部分完成的作業。

Increment(UInt64)

遞增特定變數並將結果儲存起來,成為不可部分完成的作業。

MemoryBarrier()

同步處理記憶體存取,如下所示:執行目前執行緒的處理器無法以下列方式重新排列指示:呼叫 MemoryBarrier() 之前的記憶體存取在呼叫 MemoryBarrier() 後的記憶體存取之後執行。

MemoryBarrierProcessWide()

提供整個處理序範圍的記憶體屏障,以確保來自任何 CPU 的讀取和寫入都無法穿越屏障。

Or(Int32, Int32)

對兩個 32 位元帶正負號的整數進行位元「OR」運算,並以結果取代第一個整數,成為不可部分完成的作業。

Or(Int64, Int64)

對兩個 64 位元帶正負號的整數進行位元「OR」運算,並以結果取代第一個整數,成為不可部分完成的作業。

Or(UInt32, UInt32)

對兩個 32 位元不帶正負號的整數進行位元「OR」運算,並以結果取代第一個整數,成為不可部分完成的作業。

Or(UInt64, UInt64)

對兩個 64 位元不帶正負號的整數進行位元「OR」運算,並以結果取代第一個整數,成為不可部分完成的作業。

Read(Int64)

傳回 64 位元的值 (載入為不可部分完成的作業)。

Read(UInt64)

傳回 64 位元不帶正負號的值,載入為不可部分完成的作業。

SpeculationBarrier()

定義記憶體柵欄以封鎖這個點之後的理論式執行,直到擱置的讀取和寫入完成為止。

適用於

執行緒安全性

此型別具備執行緒安全。

另請參閱