This documentation is archived and is not being maintained.

Interlocked.CompareExchange Method (Double%, Double, Double)

Compares two double-precision floating point numbers for equality and, if they are equal, replaces one of the values.

Namespace:  System.Threading
Assembly:  mscorlib (in mscorlib.dll)

public static double CompareExchange(
	ref double location1,
	double value,
	double comparand


Type: System.Double%

The destination, whose value is compared with comparand and possibly replaced.

Type: System.Double

The value that replaces the destination value if the comparison results in equality.

Type: System.Double

The value that is compared to the value at location1.

Return Value

Type: System.Double
The original value in location1.


The address of location1 is a null pointer.

If comparand and the value in location1 are equal, then value is stored in location1. Otherwise, no operation is performed. The compare and exchange operations are performed as an atomic operation. The return value of CompareExchange is the original value in location1, whether or not the exchange takes place.

The following code example demonstrates a thread-safe method that accumulates a running total of Double values. Two threads add a series of Double values using the thread-safe method and ordinary addition, and when the threads complete the totals are compared. On a dual-processor computer, there is a significant difference in the totals.

In the thread-safe method, the initial value of the running total is saved, and then the CompareExchange method is used to exchange the newly computed total with the old total. If the return value is not equal to the saved value of the running total, then another thread has updated the total in the meantime. In that case, the attempt to update the running total must be repeated.

// 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;
            // 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";
        Thread t2 = new Thread(TestThread);
        t2.Name = "Thread 2";

        // Now let the threads begin adding random numbers to  
        // the total.

        // Wait until all the threads are done.

        Console.WriteLine("Thread safe: {0}  Ordinary Double: {1}", 
            ts.Total, control);

    private static void TestThread()
        // Wait until the signal.

        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;

/* On a dual-processor computer, this code example produces output 
   similar to the following:

Thread safe: 998068.049623744  Ordinary Double: 759775.417190589

Windows 7, Windows Vista, Windows XP SP2, Windows XP Media Center Edition, Windows XP Professional x64 Edition, Windows XP Starter Edition, Windows Server 2008 R2, Windows Server 2008, Windows Server 2003, Windows Server 2000 SP4, Windows Millennium Edition, Windows 98

The .NET Framework and .NET Compact Framework do not support all versions of every platform. For a list of the supported versions, see .NET Framework System Requirements.

.NET Framework

Supported in: 3.5, 3.0, 2.0