CompareAndExchange On Three原子变量

时间:2013-10-26 08:07:11

标签: c++ multithreading c++11 atomic

我想比较并交换3个原子变量:

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);

但是如果在阅读expectednew变量并将它们与a进行比较之间,另一个线程会改变它们的值,当前线程将按先前的值工作,所以我将代码更改为它:

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;
}

我的代码是否正确?或者有更好的方法吗?

2 个答案:

答案 0 :(得分:3)

您的重写功能仍然会产生不一致的结果。如果expected在您加载到newExpectedValue之后,但在检查newExpectedValue == expectedValue之前是否发生了变化,该怎么办?如果newexpected在您加载expected之后但在new之前发生了变化,该怎么办?

这并不是指如何使用原子。如果您需要以原子方式执行涉及三个变量的操作,则应该在操作期间使用锁定序列化访问。互斥锁或自旋锁在这里更合适。

答案 1 :(得分:1)

为什么expectednew首先是原子的?通常,您在某个线程上以某种方式计算新值,而仅该线程知道新值,并执行compare_exchange。类似地,expected的值是该线程开始计算之前的旧值 - 但是预期的旧值对于那个线程来说只是重要的。

简而言之:expectednew不应跨线程共享。