比较和交换三个原子变量

CompareAndExchange On Three atomic variable

本文关键字:三个 变量 交换 比较      更新时间:2023-10-16

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

我的代码正确吗?或者有更好的方法可以做到这一点吗?

重写的函数仍可能给出不一致的结果。如果在将其加载到 newExpectedValue 后但在检查是否newExpectedValue == expectedValue之前expected更改怎么办?如果在加载expected后但在new之前更改newexpected怎么办?

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

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

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