Interlocked 类
定义
重要
一些信息与预发行产品相关,相应产品在发行之前可能会进行重大修改。 对于此处提供的信息,Microsoft 不作任何明示或暗示的担保。
为多个线程共享的变量提供原子操作。
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
注解
此类的方法有助于防止当计划程序切换上下文时,当线程更新可由其他线程访问的变量时,或者当两个线程同时在单独的处理器上执行时,可能会出现的错误。 此类的成员不会引发异常。
Decrement和Increment方法递增或递减变量,并将结果值存储在单个操作中。 在大多数计算机上,递增变量不是原子操作,需要以下步骤:
将实例变量的值加载到寄存器中。
递增或递减值。
将值存储在实例变量中。
如果不使用 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) |
比较指定的引用类型 |
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) |
以原子操作的形式,将指定类型 |
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() |
定义内存防护,用于阻止超过此点的预测执行,直至完成挂起的读取和写入操作。 |
适用于
线程安全性
此类型是线程安全的。