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

注解

此类的方法有助于防止当计划程序切换上下文时,当线程更新可由其他线程访问的变量时,或者当两个线程同时在单独的处理器上执行时,可能会出现的错误。 此类的成员不会引发异常。

DecrementIncrement方法递增或递减变量,并将结果值存储在单个操作中。 在大多数计算机上,递增变量不是原子操作,需要以下步骤:

  1. 将实例变量的值加载到寄存器中。

  2. 递增或递减值。

  3. 将值存储在实例变量中。

如果不使用 Increment 并且 Decrement执行前两个步骤后,可以抢占线程。 然后,另一个线程可以执行所有三个步骤。 当第一个线程恢复执行时,它会覆盖实例变量中的值,并丢失第二个线程执行的递增或递减的效果。

该方法 Add 以原子方式将整数值添加到整数变量,并返回该变量的新值。

该方法 Exchange 以原子方式交换指定变量的值。 该方法 CompareExchange 结合两个操作:根据比较的结果,比较两个值,并将第三个值存储在其中一个变量中。 比较和交换操作作为原子操作执行。

确保对共享变量的任何写入或读取访问权限都是原子的。 否则,数据可能会损坏,或者加载的值可能不正确。

方法

Add(Int32, Int32)

对两个 32 位整数进行求和并用和替换第一个整数,上述操作作为一个原子操作完成。

Add(Int64, Int64)

对两个 64 位整数进行求和并用和替换第一个整数,上述操作作为一个原子操作完成。

Add(UInt32, UInt32)

对两个 32 位无符号整数进行求和并用和替换第一个整数,上述操作作为一个原子操作完成。

Add(UInt64, UInt64)

对两个 64 位无符号整数进行求和并用和替换第一个整数,上述操作作为一个原子操作完成。

And(Int32, Int32)

对两个 32 位带符号整数进行按位“与”运算,并用结果替换第一个整数,上述操作作为一个原子操作完成。

And(Int64, Int64)

对两个 64 位带符号整数进行按位“与”运算,并用结果替换第一个整数,上述操作作为一个原子操作完成。

And(UInt32, UInt32)

对两个 32 位无符号整数进行按位“与”运算,并用结果替换第一个整数,上述操作作为一个原子操作完成。

And(UInt64, UInt64)

对两个 64 位无符号整数进行按位“与”运算,并用结果替换第一个整数,上述操作作为一个原子操作完成。

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(UIntPtr, UIntPtr, UIntPtr)

比较两个平台特定的句柄或指针是否相等,如果相等,则替换第一个。

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(UIntPtr, UIntPtr)

以原子操作的形式,将平台特定的句柄或指针设置为指定的值并返回原始值。

Exchange<T>(T, T)

以原子操作的形式,将指定类型 T 的变量设置为指定的值并返回原始值。

Increment(Int32)

以原子操作的形式递增指定变量的值并存储结果。

Increment(Int64)

以原子操作的形式递增指定变量的值并存储结果。

Increment(UInt32)

以原子操作的形式递增指定变量的值并存储结果。

Increment(UInt64)

以原子操作的形式递增指定变量的值并存储结果。

MemoryBarrier()

按如下方式同步内存存取:执行当前线程的处理器在对指令重新排序时,不能采用先执行 MemoryBarrier() 调用之后的内存存取,再执行 MemoryBarrier() 调用之前的内存存取的方式。

MemoryBarrierProcessWide()

提供覆盖整个过程的内存屏障,确保来自任何 CPU 的读写都不能越过该屏障。

Or(Int32, Int32)

对两个 32 位带符号整数进行按位“或”运算,并用结果替换第一个整数,上述操作作为一个原子操作完成。

Or(Int64, Int64)

对两个 64 位带符号整数进行按位“或”运算,并用结果替换第一个整数,上述操作作为一个原子操作完成。

Or(UInt32, UInt32)

对两个 32 位无符号整数进行按位“或”运算,并用结果替换第一个整数,上述操作作为一个原子操作完成。

Or(UInt64, UInt64)

对两个 64 位无符号整数进行按位“或”运算,并用结果替换第一个整数,上述操作作为一个原子操作完成。

Read(Int64)

返回一个以原子操作形式加载的 64 位值。

Read(UInt64)

返回一个以原子操作形式加载的 64 位无符号值。

SpeculationBarrier()

定义内存防护,用于阻止超过此点的预测执行,直至完成挂起的读取和写入操作。

适用于

线程安全性

此类型是线程安全的。

另请参阅