CompareAndExchange On Three atomic variable

2019-07-25 11:11发布

I want to compare and exchange 3 atomic variable:

std::atomic<int> a;
std::atomic<int> expected;
std::atomic<int> new;

int expectedValue = std::atomic_load_explicit(&expected, std::memory_order_relaxed);
int newValue = std::atomic_load_explicit(&new, std::memory_order_relaxed);

std::atomic_compare_exchange_strong_explicit(
    &a, 
    &expectedValue, 
    newValue, 
    std::memory_order_relaxed, 
    std::memory_order_relaxed);

But if in between reading expected and new variables and comparing them to a, one another thread change theirs values, current thread will work by previous values, so i change code to it:

while(true)
{
    int expectedValue = std::atomic_load_explicit(&expected, std::memory_order_relaxed);
    int newValue = std::atomic_load_explicit(&new, std::memory_order_relaxed);

    std::atomic_compare_exchange_strong_explicit(
        &a, 
        &expectedValue, 
        newValue, 
        std::memory_order_relaxed, 
        std::memory_order_relaxed);

    int newExpectedValue = std::atomic_load_explicit(&expected, std::memory_order_relaxed);
    int newNewValue = std::atomic_load_explicit(&new, std::memory_order_relaxed);

    if(newExpectedValue == expectedValue && newNewValue == newValue)
        break;
}

Is my code correct? or is there a better way to do this?

2条回答
Luminary・发光体
2楼-- · 2019-07-25 11:45

Why are expected and new atomic in the first place? Typically, you compute the new value somehow on some thread, and only that thread knows the new value, and does the compare_exchange. Similarly, the value of expected is the old value before that thread started it's computation - but that expected, old value is again only important for that one thread.

In short: expected and new should not be shared across threads.

查看更多
倾城 Initia
3楼-- · 2019-07-25 12:01

Your rewritten function can still give inconsistent results. What if expected changes after you load it into newExpectedValue, but before you check if newExpectedValue == expectedValue? What if new and expected change after you load expected, but before new?

This isn't how atomics are intended to be used. If you need to do an operation involving three variables atomically, you should be using a lock to serialize access during the operation. A mutex or spin lock would be more appropriate here.

查看更多
登录 后发表回答