c++c++11atomicstdatomiccompare-and-swap

C++ Atomic compare_exchange_weak succeeds the second time, even though I haven't changed expected?


Something happened when I used this feature that Was hard for me to understand Code:

#include<iostream>
#include<atomic>
int main()
{
    std::atomic_size_t example;
    size_t expect = 1000;
    example.store(100, std::memory_order_release);
    //Now example.load() is 100;
    auto result = example.compare_exchange_weak(expect, 50, std::memory_order_relaxed);
    //Now result is zero(false) and example.load() is 100,I knew it would.
    result = example.compare_exchange_weak(expect, 50, std::memory_order_relaxed);
    //But now !!! result is One(true)! and example.load() is 50 Why???
}

What happens after the function is executed? Why are the two executions different? I can't understand why this happened, so I really hope you can answer my question.Thank u very much.

I perfected this code, and now it compiles and executes properly, it's just a single thread.


Solution

  • It is called an exchange for a reason.

    Calling example.compare_exchange_weak(expected, value); roughly corresponds to the following piece of code done atomically:

    if (expected==example){
        example = value;
        return true;
    }
    else
    {
        expected = example;
        return false;
    }
    

    In your first call, the else branch is taken meaning expected<-100 as 100 is the present value in example which is not altered.

    The next call compares example to expected and they are obviously equal, so the if branch is taken. Thus example==100 after the second call.

    See the documentation for more detailed information.

    This behavior is useful because you can always save the expected value somewhere safe and use a "burner" variable and this way you also get the currently stored value in example. Another way of looking at this: after the call expected will always contain the value stored in example before the call was made.