1

我想比较和交换 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;
}

我的代码正确吗?还是有更好的方法来做到这一点?

4

2 回答 2

3

您重写的函数仍然会给出不一致的结果。如果expected在将其加载到newExpectedValue之后但在检查 if 之前发生更改newExpectedValue == expectedValue怎么办?如果在加载之后但之前进行new更改怎么办?expectedexpectednew

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

于 2013-10-26T08:17:10.887 回答
1

为什么首先是原子的expectednew通常,您在某个线程上以某种方式计算新值,并且只有该线程知道新值并执行 compare_exchange。同样, 的值expected是该线程开始计算之前的旧值 - 但预期的旧值再次仅对那个线程重要。

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

于 2013-10-26T08:42:33.580 回答