Interlocked.CompareExchange 方法  
定义
重要
一些信息与预发行产品相关,相应产品在发行之前可能会进行重大修改。 对于此处提供的信息,Microsoft 不作任何明示或暗示的担保。
比较两个值是否相等,如果相等,则替换第一个值作为原子操作。
重载
| CompareExchange(UIntPtr, UIntPtr, UIntPtr) | 比较两个特定于平台的句柄或指针是否相等,如果它们相等,则替换第一个句柄作为原子操作。 | 
| CompareExchange(UInt64, UInt64, UInt64) | 比较两个 64 位无符号整数是否相等,如果相等,请将第一个值替换为原子运算。 | 
| CompareExchange(UInt32, UInt32, UInt32) | 比较两个 32 位无符号整数是否相等,如果相等,则替换第一个值作为原子运算。 | 
| CompareExchange(UInt16, UInt16, UInt16) | 比较两个 16 位有符号整数是否相等,如果相等,则替换第一个值作为原子运算。 | 
| CompareExchange(Single, Single, Single) | 比较两个单精度浮点数是否相等,如果相等,则替换第一个值作为原子运算。 | 
| CompareExchange(Object, Object, Object) | 比较两个对象的引用相等性,如果两个对象相等,则替换第一个对象作为原子操作。 | 
| CompareExchange(SByte, SByte, SByte) | 比较两个 8 位有符号整数是否相等,如果相等,则替换第一个值作为原子操作。 | 
| CompareExchange(Int64, Int64, Int64) | 比较两个 64 位有符号整数是否相等,如果相等,则替换第一个值作为原子运算。 | 
| CompareExchange(Int32, Int32, Int32) | 比较两个 32 位有符号整数是否相等,如果相等,则替换第一个值作为原子运算。 | 
| CompareExchange(Int16, Int16, Int16) | 比较两个 16 位无符号整数是否相等,如果相等,则替换第一个值作为原子运算。 | 
| CompareExchange(Double, Double, Double) | 比较两个双精度浮点数是否相等,如果相等,则替换第一个值作为原子运算。 | 
| CompareExchange(Byte, Byte, Byte) | 比较两个 8 位无符号整数是否相等,如果相等,则替换第一个值作为原子操作。 | 
| CompareExchange(IntPtr, IntPtr, IntPtr) | 比较两个特定于平台的句柄或指针是否相等,如果它们相等,则替换第一个句柄作为原子操作。 | 
| CompareExchange<T>(T, T, T) | 比较指定引用类型的两个实例, | 
CompareExchange(UIntPtr, UIntPtr, UIntPtr)
- Source:
- Interlocked.cs
- Source:
- Interlocked.cs
- Source:
- Interlocked.cs
- Source:
- Interlocked.cs
重要
此 API 不符合 CLS。
比较两个特定于平台的句柄或指针是否相等,如果它们相等,则替换第一个句柄作为原子操作。
public:
 static UIntPtr CompareExchange(UIntPtr % location1, UIntPtr value, UIntPtr comparand);[System.CLSCompliant(false)]
public static UIntPtr CompareExchange(ref UIntPtr location1, UIntPtr value, UIntPtr comparand);[<System.CLSCompliant(false)>]
static member CompareExchange : unativeint * unativeint * unativeint -> unativeintPublic Shared Function CompareExchange (ByRef location1 As UIntPtr, value As UIntPtr, comparand As UIntPtr) As UIntPtr参数
返回
unativeint
              location1中的原始值。
- 属性
例外
              location1 的地址是 null 指针。
适用于
CompareExchange(UInt64, UInt64, UInt64)
- Source:
- Interlocked.cs
- Source:
- Interlocked.cs
- Source:
- Interlocked.cs
- Source:
- Interlocked.cs
重要
此 API 不符合 CLS。
比较两个 64 位无符号整数是否相等,如果相等,请将第一个值替换为原子运算。
public:
 static System::UInt64 CompareExchange(System::UInt64 % location1, System::UInt64 value, System::UInt64 comparand);[System.CLSCompliant(false)]
public static ulong CompareExchange(ref ulong location1, ulong value, ulong comparand);[<System.CLSCompliant(false)>]
static member CompareExchange : uint64 * uint64 * uint64 -> uint64Public Shared Function CompareExchange (ByRef location1 As ULong, value As ULong, comparand As ULong) As ULong参数
- location1
- UInt64
目标,其值与 comparand 进行比较,并可能替换。
- value
- UInt64
如果比较结果相等,则替换目标值的值。
- comparand
- UInt64
与 location1的值进行比较的值。
返回
              location1中的原始值。
- 属性
例外
              location1 的地址是 null 指针。
适用于
CompareExchange(UInt32, UInt32, UInt32)
- Source:
- Interlocked.cs
- Source:
- Interlocked.cs
- Source:
- Interlocked.cs
- Source:
- Interlocked.cs
重要
此 API 不符合 CLS。
比较两个 32 位无符号整数是否相等,如果相等,则替换第一个值作为原子运算。
public:
 static System::UInt32 CompareExchange(System::UInt32 % location1, System::UInt32 value, System::UInt32 comparand);[System.CLSCompliant(false)]
public static uint CompareExchange(ref uint location1, uint value, uint comparand);[<System.CLSCompliant(false)>]
static member CompareExchange : uint32 * uint32 * uint32 -> uint32Public Shared Function CompareExchange (ByRef location1 As UInteger, value As UInteger, comparand As UInteger) As UInteger参数
- location1
- UInt32
目标,其值与 comparand 进行比较,并可能替换。
- value
- UInt32
如果比较结果相等,则替换目标值的值。
- comparand
- UInt32
与 location1的值进行比较的值。
返回
              location1中的原始值。
- 属性
例外
              location1 的地址是 null 指针。
适用于
CompareExchange(UInt16, UInt16, UInt16)
- Source:
- Interlocked.cs
重要
此 API 不符合 CLS。
比较两个 16 位有符号整数是否相等,如果相等,则替换第一个值作为原子运算。
public:
 static System::UInt16 CompareExchange(System::UInt16 % location1, System::UInt16 value, System::UInt16 comparand);[System.CLSCompliant(false)]
public static ushort CompareExchange(ref ushort location1, ushort value, ushort comparand);[<System.CLSCompliant(false)>]
static member CompareExchange : uint16 * uint16 * uint16 -> uint16Public Shared Function CompareExchange (ByRef location1 As UShort, value As UShort, comparand As UShort) As UShort参数
- location1
- UInt16
目标,其值与 comparand 进行比较,并可能替换。
- value
- UInt16
如果比较结果相等,则替换目标值的值。
- comparand
- UInt16
与 location1的值进行比较的值。
返回
              location1中的原始值。
- 属性
例外
              location1 的地址是 null 指针。
适用于
CompareExchange(Single, Single, Single)
- Source:
- Interlocked.cs
- Source:
- Interlocked.cs
- Source:
- Interlocked.cs
- Source:
- Interlocked.cs
比较两个单精度浮点数是否相等,如果相等,则替换第一个值作为原子运算。
public:
 static float CompareExchange(float % location1, float value, float comparand);public static float CompareExchange(ref float location1, float value, float comparand);static member CompareExchange : single * single * single -> singlePublic Shared Function CompareExchange (ByRef location1 As Single, value As Single, comparand As Single) As Single参数
- location1
- Single
目标,其值与 comparand 进行比较,并可能替换。
- value
- Single
如果比较结果相等,则替换目标值的值。
- comparand
- Single
与 location1的值进行比较的值。
返回
              location1中的原始值。
例外
              location1 的地址为 null 指针。
示例
下面的代码示例演示了一种线程安全方法,该方法累积了总 Single 值。 两个线程使用线程安全方法和普通加法添加一系列 Single 值,并在线程完成总计时进行比较。 在双处理器计算机上,总计存在显著差异。
在线程安全方法中,保存运行总计的初始值,然后使用 CompareExchange 方法将新计算的总和与旧总计交换。 如果返回值不等于正在运行总计的已保存值,则另一个线程同时更新了总计。 在这种情况下,必须重复尝试更新正在运行的总和。
// This example demonstrates a thread-safe method that adds to a
// running total.  
using System;
using System.Threading;
public class ThreadSafe
{
    // Field totalValue contains a running total that can be updated
    // by multiple threads. It must be protected from unsynchronized 
    // access.
    private float totalValue = 0.0F;
    // The Total property returns the running total.
    public float Total { get { return totalValue; }}
    // AddToTotal safely adds a value to the running total.
    public float AddToTotal(float addend)
    {
        float initialValue, computedValue;
        do
        {
            // Save the current running total in a local variable.
            initialValue = totalValue;
            // Add the new value to the running total.
            computedValue = initialValue + addend;
            // CompareExchange compares totalValue to initialValue. If
            // they are not equal, then another thread has updated the
            // running total since this loop started. CompareExchange
            // does not update totalValue. CompareExchange returns the
            // contents of totalValue, which do not equal initialValue,
            // so the loop executes again.
        }
        while (initialValue != Interlocked.CompareExchange(ref totalValue, 
            computedValue, initialValue));
        // If no other thread updated the running total, then 
        // totalValue and initialValue are equal when CompareExchange
        // compares them, and computedValue is stored in totalValue.
        // CompareExchange returns the value that was in totalValue
        // before the update, which is equal to initialValue, so the 
        // loop ends.
        // The function returns computedValue, not totalValue, because
        // totalValue could be changed by another thread between
        // the time the loop ends and the function returns.
        return computedValue;
    }
}
public class Test
{
    // Create an instance of the ThreadSafe class to test.
    private static ThreadSafe ts = new ThreadSafe();
    private static float control;
    private static Random r = new Random();
    private static ManualResetEvent mre = new ManualResetEvent(false);
    public static void Main()
    {
        // Create two threads, name them, and start them. The
        // thread will block on mre.
        Thread t1 = new Thread(TestThread);
        t1.Name = "Thread 1";
        t1.Start();
        Thread t2 = new Thread(TestThread);
        t2.Name = "Thread 2";
        t2.Start();
        // Now let the threads begin adding random numbers to 
        // the total.
        mre.Set();
        
        // Wait until all the threads are done.
        t1.Join();
        t2.Join();
        Console.WriteLine("Thread safe: {0}  Ordinary float: {1}", 
            ts.Total, control);
    }
    private static void TestThread()
    {
        // Wait until the signal.
        mre.WaitOne();
        for(int i = 1; i <= 1000000; i++)
        {
            // Add to the running total in the ThreadSafe instance, and
            // to an ordinary float.
            //
            float testValue = (float) r.NextDouble();
            control += testValue;
            ts.AddToTotal(testValue);
        }
    }
}
/* On a dual-processor computer, this code example produces output 
   similar to the following:
Thread safe: 17039.57  Ordinary float: 15706.44
 */
' This example demonstrates a thread-safe method that adds to a
' running total.  
Imports System.Threading
Public Class ThreadSafe
    ' Field totalValue contains a running total that can be updated
    ' by multiple threads. It must be protected from unsynchronized 
    ' access.
    Private totalValue As Single = 0.0
    ' The Total property returns the running total.
    Public ReadOnly Property Total As Single
        Get
            Return totalValue
        End Get
    End Property
    ' AddToTotal safely adds a value to the running total.
    Public Function AddToTotal(ByVal addend As Single) As Single
        Dim initialValue, computedValue As Single
        Do
            ' Save the current running total in a local variable.
            initialValue = totalValue
            ' Add the new value to the running total.
            computedValue = initialValue + addend
            ' CompareExchange compares totalValue to initialValue. If
            ' they are not equal, then another thread has updated the
            ' running total since this loop started. CompareExchange
            ' does not update totalValue. CompareExchange returns the
            ' contents of totalValue, which do not equal initialValue,
            ' so the loop executes again.
        Loop While initialValue <> Interlocked.CompareExchange( _
            totalValue, computedValue, initialValue)
        ' If no other thread updated the running total, then 
        ' totalValue and initialValue are equal when CompareExchange
        ' compares them, and computedValue is stored in totalValue.
        ' CompareExchange returns the value that was in totalValue
        ' before the update, which is equal to initialValue, so the 
        ' loop ends.
        ' The function returns computedValue, not totalValue, because
        ' totalValue could be changed by another thread between
        ' the time the loop ends and the function returns.
        Return computedValue
    End Function
End Class
Public Class Test
    ' Create an instance of the ThreadSafe class to test.
    Private Shared ts As New ThreadSafe()
    Private Shared control As Single
    Private Shared r As New Random()
    Private Shared mre As New ManualResetEvent(false)
    <MTAThread> _
    Public Shared Sub Main()
        ' Create two threads, name them, and start them. The
        ' threads will block on mre.
        Dim t1 As New Thread(AddressOf TestThread)
        t1.Name = "Thread 1"
        t1.Start()
        Dim t2 As New Thread(AddressOf TestThread)
        t2.Name = "Thread 2"
        t2.Start()
        ' Now let the threads begin adding random numbers to 
        ' the total.
        mre.Set()
        
        ' Wait until all the threads are done.
        t1.Join()
        t2.Join()
        Console.WriteLine("Thread safe: {0}  Ordinary Single: {1}", ts.Total, control)
    End Sub
    Private Shared Sub TestThread()
        ' Wait until the signal.
        mre.WaitOne()
        For i As Integer = 1 to 1000000
            ' Add to the running total in the ThreadSafe instance, and
            ' to an ordinary Single.
            '
            Dim testValue As Single = r.NextDouble()
            control += testValue
            ts.AddToTotal(testValue)
        Next
    End Sub
End Class
' On a dual-processor computer, this code example produces output 
' similar to the following:
'
'Thread safe: 17039.57  Ordinary Single: 15706.44
注解
如果 comparand 且 location1 中的值相等,则 value 存储在 location1中。 否则,不执行任何操作。 比较和交换操作作为原子操作执行。 
              CompareExchange 的返回值是 location1中的原始值,无论交换是否发生。
另请参阅
适用于
CompareExchange(Object, Object, Object)
- Source:
- Interlocked.CoreCLR.cs
- Source:
- Interlocked.cs
- Source:
- Interlocked.cs
- Source:
- Interlocked.CoreCLR.cs
比较两个对象的引用相等性,如果两个对象相等,则替换第一个对象作为原子操作。
public:
 static System::Object ^ CompareExchange(System::Object ^ % location1, System::Object ^ value, System::Object ^ comparand);public static object CompareExchange(ref object location1, object value, object comparand);public static object? CompareExchange(ref object? location1, object? value, object? comparand);static member CompareExchange : obj * obj * obj -> objPublic Shared Function CompareExchange (ByRef location1 As Object, value As Object, comparand As Object) As Object参数
- location1
- Object
通过引用与 comparand 比较并可能替换的目标对象。
- value
- Object
如果引用比较结果相等,则替换目标对象的对象。
- comparand
- Object
通过引用 location1对象进行比较的对象。
返回
              location1中的原始值。
例外
              location1 的地址是 null 指针。
注解
重要
从 .NET Framework 2.0 开始,CompareExchange<T>(T, T, T) 方法重载为引用类型提供类型安全的替代方法。 建议调用它,而不是此重载。
如果 comparand 和 location1 中的对象按引用相等,则 value 存储在 location1中。 否则,不执行任何操作。 比较和交换操作作为原子操作执行。 
              CompareExchange 的返回值是 location1中的原始值,无论交换是否发生。
注意
将对象与引用相等性而不是值相等性进行比较。 因此,具有相同值类型的两个装箱实例(例如整数 3)始终不相等,并且不执行任何操作。 不要将此重载用于值类型。
另请参阅
适用于
CompareExchange(SByte, SByte, SByte)
- Source:
- Interlocked.cs
重要
此 API 不符合 CLS。
比较两个 8 位有符号整数是否相等,如果相等,则替换第一个值作为原子操作。
public:
 static System::SByte CompareExchange(System::SByte % location1, System::SByte value, System::SByte comparand);[System.CLSCompliant(false)]
public static sbyte CompareExchange(ref sbyte location1, sbyte value, sbyte comparand);[<System.CLSCompliant(false)>]
static member CompareExchange : sbyte * sbyte * sbyte -> sbytePublic Shared Function CompareExchange (ByRef location1 As SByte, value As SByte, comparand As SByte) As SByte参数
- location1
- SByte
目标,其值与 comparand 进行比较,并可能替换。
- value
- SByte
如果比较结果相等,则替换目标值的值。
- comparand
- SByte
与 location1的值进行比较的值。
返回
              location1中的原始值。
- 属性
例外
              location1 的地址是 null 指针。
适用于
CompareExchange(Int64, Int64, Int64)
- Source:
- Interlocked.CoreCLR.cs
- Source:
- Interlocked.cs
- Source:
- Interlocked.cs
- Source:
- Interlocked.CoreCLR.cs
比较两个 64 位有符号整数是否相等,如果相等,则替换第一个值作为原子运算。
public:
 static long CompareExchange(long % location1, long value, long comparand);public static long CompareExchange(ref long location1, long value, long comparand);static member CompareExchange : int64 * int64 * int64 -> int64Public Shared Function CompareExchange (ByRef location1 As Long, value As Long, comparand As Long) As Long参数
- location1
- Int64
目标,其值与 comparand 进行比较,并可能替换。
- value
- Int64
如果比较结果相等,则替换目标值的值。
- comparand
- Int64
与 location1的值进行比较的值。
返回
              location1中的原始值。
例外
              location1 的地址为 null 指针。
注解
如果 comparand 且 location1 中的值相等,则 value 存储在 location1中。 否则,不执行任何操作。 比较和交换操作作为原子操作执行。 
              CompareExchange 的返回值是 location1中的原始值,无论交换是否发生。
另请参阅
适用于
CompareExchange(Int32, Int32, Int32)
- Source:
- Interlocked.CoreCLR.cs
- Source:
- Interlocked.cs
- Source:
- Interlocked.cs
- Source:
- Interlocked.CoreCLR.cs
比较两个 32 位有符号整数是否相等,如果相等,则替换第一个值作为原子运算。
public:
 static int CompareExchange(int % location1, int value, int comparand);public static int CompareExchange(ref int location1, int value, int comparand);static member CompareExchange : int * int * int -> intPublic Shared Function CompareExchange (ByRef location1 As Integer, value As Integer, comparand As Integer) As Integer参数
- location1
- Int32
目标,其值与 comparand 进行比较,并可能替换。
- value
- Int32
如果比较结果相等,则替换目标值的值。
- comparand
- Int32
与 location1的值进行比较的值。
返回
              location1中的原始值。
例外
              location1 的地址为 null 指针。
示例
下面的代码示例演示了一种线程安全方法,该方法累积了总运行总数。 保存运行总计的初始值,然后使用 CompareExchange 方法将新计算的总和与旧总计交换。 如果返回值不等于正在运行总计的已保存值,则另一个线程同时更新了总计。 在这种情况下,必须重复尝试更新正在运行的总和。
注意
.NET Framework 版本 2.0 中引入的 Add 方法为整数累积线程安全的运行总计提供了更方便的方法。
// This example demonstrates a thread-safe method that adds to a
// running total.  It cannot be run directly.  You can compile it
// as a library, or add the class to a project.
using System.Threading;
public class ThreadSafe {
    // totalValue contains a running total that can be updated
    // by multiple threads. It must be protected from unsynchronized 
    // access.
    private int totalValue = 0;
    // The Total property returns the running total.
    public int Total {
        get { return totalValue; }
    }
    // AddToTotal safely adds a value to the running total.
    public int AddToTotal(int addend) {
        int initialValue, computedValue;
        do {
            // Save the current running total in a local variable.
            initialValue = totalValue;
            // Add the new value to the running total.
            computedValue = initialValue + addend;
            // CompareExchange compares totalValue to initialValue. If
            // they are not equal, then another thread has updated the
            // running total since this loop started. CompareExchange
            // does not update totalValue. CompareExchange returns the
            // contents of totalValue, which do not equal initialValue,
            // so the loop executes again.
        } while (initialValue != Interlocked.CompareExchange(
            ref totalValue, computedValue, initialValue));
        // If no other thread updated the running total, then 
        // totalValue and initialValue are equal when CompareExchange
        // compares them, and computedValue is stored in totalValue.
        // CompareExchange returns the value that was in totalValue
        // before the update, which is equal to initialValue, so the 
        // loop ends.
        // The function returns computedValue, not totalValue, because
        // totalValue could be changed by another thread between
        // the time the loop ends and the function returns.
        return computedValue;
    }
}
' This example demonstrates a thread-safe method that adds to a
' running total.  It cannot be run directly.  You can compile it
' as a library, or add the class to a project.
Imports System.Threading
Public Class ThreadSafe
    ' Field totalValue contains a running total that can be updated
    ' by multiple threads. It must be protected from unsynchronized 
    ' access.
    Private totalValue As Integer = 0
    ' The Total property returns the running total.
    Public ReadOnly Property Total As Integer
        Get
            Return totalValue
        End Get
    End Property
    ' AddToTotal safely adds a value to the running total.
    Public Function AddToTotal(ByVal addend As Integer) As Integer
        Dim initialValue, computedValue As Integer
        Do
            ' Save the current running total in a local variable.
            initialValue = totalValue
            ' Add the new value to the running total.
            computedValue = initialValue + addend
            ' CompareExchange compares totalValue to initialValue. If
            ' they are not equal, then another thread has updated the
            ' running total since this loop started. CompareExchange
            ' does not update totalValue. CompareExchange returns the
            ' contents of totalValue, which do not equal initialValue,
            ' so the loop executes again.
        Loop While initialValue <> Interlocked.CompareExchange( _
            totalValue, computedValue, initialValue)
        ' If no other thread updated the running total, then 
        ' totalValue and initialValue are equal when CompareExchange
        ' compares them, and computedValue is stored in totalValue.
        ' CompareExchange returns the value that was in totalValue
        ' before the update, which is equal to initialValue, so the 
        ' loop ends.
        ' The function returns computedValue, not totalValue, because
        ' totalValue could be changed by another thread between
        ' the time the loop ends and the function returns.
        Return computedValue
    End Function
End Class
注解
如果 comparand 且 location1 中的值相等,则 value 存储在 location1中。 否则,不执行任何操作。 比较和交换操作作为原子操作执行。 
              CompareExchange 的返回值是 location1中的原始值,无论交换是否发生。
另请参阅
适用于
CompareExchange(Int16, Int16, Int16)
- Source:
- Interlocked.cs
比较两个 16 位无符号整数是否相等,如果相等,则替换第一个值作为原子运算。
public:
 static short CompareExchange(short % location1, short value, short comparand);public static short CompareExchange(ref short location1, short value, short comparand);static member CompareExchange : int16 * int16 * int16 -> int16Public Shared Function CompareExchange (ByRef location1 As Short, value As Short, comparand As Short) As Short参数
- location1
- Int16
目标,其值与 comparand 进行比较,并可能替换。
- value
- Int16
如果比较结果相等,则替换目标值的值。
- comparand
- Int16
与 location1的值进行比较的值。
返回
              location1中的原始值。
例外
              location1 的地址是 null 指针。
适用于
CompareExchange(Double, Double, Double)
- Source:
- Interlocked.cs
- Source:
- Interlocked.cs
- Source:
- Interlocked.cs
- Source:
- Interlocked.cs
比较两个双精度浮点数是否相等,如果相等,则替换第一个值作为原子运算。
public:
 static double CompareExchange(double % location1, double value, double comparand);public static double CompareExchange(ref double location1, double value, double comparand);static member CompareExchange : double * double * double -> doublePublic Shared Function CompareExchange (ByRef location1 As Double, value As Double, comparand As Double) As Double参数
- location1
- Double
目标,其值与 comparand 进行比较,并可能替换。
- value
- Double
如果比较结果相等,则替换目标值的值。
- comparand
- Double
与 location1的值进行比较的值。
返回
              location1中的原始值。
例外
              location1 的地址为 null 指针。
示例
下面的代码示例演示了一种线程安全方法,该方法累积了总 Double 值。 两个线程使用线程安全方法和普通加法添加一系列 Double 值,并在线程完成总计时进行比较。 在双处理器计算机上,总计存在显著差异。
在线程安全方法中,保存运行总计的初始值,然后使用 CompareExchange 方法将新计算的总和与旧总计交换。 如果返回值不等于正在运行总计的已保存值,则另一个线程同时更新了总计。 在这种情况下,必须重复尝试更新正在运行的总和。
// This example demonstrates a thread-safe method that adds to a
// running total.  
using System;
using System.Threading;
public class ThreadSafe
{
    // Field totalValue contains a running total that can be updated
    // by multiple threads. It must be protected from unsynchronized 
    // access.
    private double totalValue = 0.0;
    // The Total property returns the running total.
    public double Total { get { return totalValue; }}
    // AddToTotal safely adds a value to the running total.
    public double AddToTotal(double addend)
    {
        double initialValue, computedValue;
        do
        {
            // Save the current running total in a local variable.
            initialValue = totalValue;
            // Add the new value to the running total.
            computedValue = initialValue + addend;
            // CompareExchange compares totalValue to initialValue. If
            // they are not equal, then another thread has updated the
            // running total since this loop started. CompareExchange
            // does not update totalValue. CompareExchange returns the
            // contents of totalValue, which do not equal initialValue,
            // so the loop executes again.
        }
        while (initialValue != Interlocked.CompareExchange(ref totalValue, 
            computedValue, initialValue));
        // If no other thread updated the running total, then 
        // totalValue and initialValue are equal when CompareExchange
        // compares them, and computedValue is stored in totalValue.
        // CompareExchange returns the value that was in totalValue
        // before the update, which is equal to initialValue, so the 
        // loop ends.
        // The function returns computedValue, not totalValue, because
        // totalValue could be changed by another thread between
        // the time the loop ends and the function returns.
        return computedValue;
    }
}
public class Test
{
    // Create an instance of the ThreadSafe class to test.
    private static ThreadSafe ts = new ThreadSafe();
    private static double control;
    private static Random r = new Random();
    private static ManualResetEvent mre = new ManualResetEvent(false);
    public static void Main()
    {
        // Create two threads, name them, and start them. The
        // thread will block on mre.
        Thread t1 = new Thread(TestThread);
        t1.Name = "Thread 1";
        t1.Start();
        Thread t2 = new Thread(TestThread);
        t2.Name = "Thread 2";
        t2.Start();
        // Now let the threads begin adding random numbers to 
        // the total.
        mre.Set();
        
        // Wait until all the threads are done.
        t1.Join();
        t2.Join();
        Console.WriteLine("Thread safe: {0}  Ordinary Double: {1}", 
            ts.Total, control);
    }
    private static void TestThread()
    {
        // Wait until the signal.
        mre.WaitOne();
        for(int i = 1; i <= 1000000; i++)
        {
            // Add to the running total in the ThreadSafe instance, and
            // to an ordinary double.
            //
            double testValue = r.NextDouble();
            control += testValue;
            ts.AddToTotal(testValue);
        }
    }
}
/* On a dual-processor computer, this code example produces output 
   similar to the following:
Thread safe: 998068.049623744  Ordinary Double: 759775.417190589
 */
' This example demonstrates a thread-safe method that adds to a
' running total.  
Imports System.Threading
Public Class ThreadSafe
    ' Field totalValue contains a running total that can be updated
    ' by multiple threads. It must be protected from unsynchronized 
    ' access.
    Private totalValue As Double = 0.0
    ' The Total property returns the running total.
    Public ReadOnly Property Total As Double
        Get
            Return totalValue
        End Get
    End Property
    ' AddToTotal safely adds a value to the running total.
    Public Function AddToTotal(ByVal addend As Double) As Double
        Dim initialValue, computedValue As Double
        Do
            ' Save the current running total in a local variable.
            initialValue = totalValue
            ' Add the new value to the running total.
            computedValue = initialValue + addend
            ' CompareExchange compares totalValue to initialValue. If
            ' they are not equal, then another thread has updated the
            ' running total since this loop started. CompareExchange
            ' does not update totalValue. CompareExchange returns the
            ' contents of totalValue, which do not equal initialValue,
            ' so the loop executes again.
        Loop While initialValue <> Interlocked.CompareExchange( _
            totalValue, computedValue, initialValue)
        ' If no other thread updated the running total, then 
        ' totalValue and initialValue are equal when CompareExchange
        ' compares them, and computedValue is stored in totalValue.
        ' CompareExchange returns the value that was in totalValue
        ' before the update, which is equal to initialValue, so the 
        ' loop ends.
        ' The function returns computedValue, not totalValue, because
        ' totalValue could be changed by another thread between
        ' the time the loop ends and the function returns.
        Return computedValue
    End Function
End Class
Public Class Test
    ' Create an instance of the ThreadSafe class to test.
    Private Shared ts As New ThreadSafe()
    Private Shared control As Double
    Private Shared r As New Random()
    Private Shared mre As New ManualResetEvent(false)
    <MTAThread> _
    Public Shared Sub Main()
        ' Create two threads, name them, and start them. The
        ' threads will block on mre.
        Dim t1 As New Thread(AddressOf TestThread)
        t1.Name = "Thread 1"
        t1.Start()
        Dim t2 As New Thread(AddressOf TestThread)
        t2.Name = "Thread 2"
        t2.Start()
        ' Now let the threads begin adding random numbers to 
        ' the total.
        mre.Set()
        
        ' Wait until all the threads are done.
        t1.Join()
        t2.Join()
        Console.WriteLine("Thread safe: {0}  Ordinary Double: {1}", ts.Total, control)
    End Sub
    Private Shared Sub TestThread()
        ' Wait until the signal.
        mre.WaitOne()
        For i As Integer = 1 to 1000000
            ' Add to the running total in the ThreadSafe instance, and
            ' to an ordinary double.
            '
            Dim testValue As Double = r.NextDouble
            control += testValue
            ts.AddToTotal(testValue)
        Next
    End Sub
End Class
' On a dual-processor computer, this code example produces output 
' similar to the following:
'
'Thread safe: 998068.049623744  Ordinary Double: 759775.417190589
注解
如果 comparand 且 location1 中的值相等,则 value 存储在 location1中。 否则,不执行任何操作。 比较和交换操作作为原子操作执行。 
              CompareExchange 的返回值是 location1中的原始值,无论交换是否发生。
另请参阅
适用于
CompareExchange(Byte, Byte, Byte)
- Source:
- Interlocked.cs
比较两个 8 位无符号整数是否相等,如果相等,则替换第一个值作为原子操作。
public:
 static System::Byte CompareExchange(System::Byte % location1, System::Byte value, System::Byte comparand);public static byte CompareExchange(ref byte location1, byte value, byte comparand);static member CompareExchange : byte * byte * byte -> bytePublic Shared Function CompareExchange (ByRef location1 As Byte, value As Byte, comparand As Byte) As Byte参数
- location1
- Byte
目标,其值与 comparand 进行比较,并可能替换。
- value
- Byte
如果比较结果相等,则替换目标值的值。
- comparand
- Byte
与 location1的值进行比较的值。
返回
              location1中的原始值。
例外
              location1 的地址是 null 指针。
适用于
CompareExchange(IntPtr, IntPtr, IntPtr)
- Source:
- Interlocked.cs
- Source:
- Interlocked.cs
- Source:
- Interlocked.cs
- Source:
- Interlocked.cs
比较两个特定于平台的句柄或指针是否相等,如果它们相等,则替换第一个句柄作为原子操作。
public:
 static IntPtr CompareExchange(IntPtr % location1, IntPtr value, IntPtr comparand);public static IntPtr CompareExchange(ref IntPtr location1, IntPtr value, IntPtr comparand);static member CompareExchange : nativeint * nativeint * nativeint -> nativeintPublic Shared Function CompareExchange (ByRef location1 As IntPtr, value As IntPtr, comparand As IntPtr) As IntPtr参数
返回
nativeint
              location1中的原始值。
例外
              location1 的地址为 null 指针。
注解
如果 comparand 且 location1 中的值相等,则 value 存储在 location1中。 否则,不执行任何操作。 比较和交换操作作为原子操作执行。 此方法的返回值是 location1中的原始值,无论交换是否发生。
注意
IntPtr 是特定于平台的类型。
另请参阅
适用于
CompareExchange<T>(T, T, T)
- Source:
- Interlocked.cs
- Source:
- Interlocked.CoreCLR.cs
- Source:
- Interlocked.CoreCLR.cs
- Source:
- Interlocked.CoreCLR.cs
比较指定引用类型的两个实例,T 引用相等,如果相等,则替换第一个实例作为原子操作。
public:
generic <typename T>
 where T : class static T CompareExchange(T % location1, T value, T comparand);public:
generic <typename T>
 static T CompareExchange(T % location1, T value, T comparand);public static T CompareExchange<T>(ref T location1, T value, T comparand) where T : class;public static T CompareExchange<T>(ref T location1, T value, T comparand);[System.Runtime.InteropServices.ComVisible(false)]
public static T CompareExchange<T>(ref T location1, T value, T comparand) where T : class;static member CompareExchange : 'T * 'T * 'T -> 'T (requires 'T : null)static member CompareExchange : 'T * 'T * 'T -> 'T[<System.Runtime.InteropServices.ComVisible(false)>]
static member CompareExchange : 'T * 'T * 'T -> 'T (requires 'T : null)Public Shared Function CompareExchange(Of T As Class) (ByRef location1 As T, value As T, comparand As T) As TPublic Shared Function CompareExchange(Of T) (ByRef location1 As T, value As T, comparand As T) As T类型参数
- T
要用于 location1、value和 comparand的类型。 此类型必须是引用类型。
参数
- location1
- T
目标,其值通过引用与 comparand 进行比较,并可能被替换。 这是一个引用参数(在 C# 中ref,在 Visual Basic 中 ByRef)。
- value
- T
如果引用的比较结果相等,则替换目标值的值。
- comparand
- T
通过引用 location1的值进行比较的值。
返回
              location1中的原始值。
- 属性
例外
              location1 的地址为 null 指针。
指定了不受支持的 T。
注解
如果 comparand 和 location1 中的值按引用相等,则 value 存储在 location1中。 否则,不执行任何操作。 比较和交换作为原子操作执行。 此方法的返回值是 location1中的原始值,无论交换是否发生。
此方法仅支持引用类型。 值类型有 CompareExchange 重载 Int32、Int64、IntPtr、Single和 Double,但不支持其他值类型。
注意
此方法重载优于 CompareExchange(Object, Object, Object) 方法重载,因为后者要求后期访问目标对象。