我想比较并交换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);
但是如果在阅读expected
和new
变量并将它们与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;
}
我的代码是否正确?或者有更好的方法吗?
答案 0 :(得分:3)
您的重写功能仍然会产生不一致的结果。如果expected
在您加载到newExpectedValue
之后,但在检查newExpectedValue == expectedValue
之前是否发生了变化,该怎么办?如果new
和expected
在您加载expected
之后但在new
之前发生了变化,该怎么办?
这并不是指如何使用原子。如果您需要以原子方式执行涉及三个变量的操作,则应该在操作期间使用锁定序列化访问。互斥锁或自旋锁在这里更合适。
答案 1 :(得分:1)
为什么expected
和new
首先是原子的?通常,您在某个线程上以某种方式计算新值,而仅该线程知道新值,并执行compare_exchange。类似地,expected
的值是该线程开始计算之前的旧值 - 但是预期的旧值对于那个线程来说只是重要的。
简而言之:expected
和new
不应跨线程共享。