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

注解

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

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)

按位“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()

定义一个内存围栏,该围栏阻止在等待读取和写入完成之前通过此点的推理执行。

适用于

线程安全性

此类型是线程安全的。

另请参阅