以宽松的顺序修改原子值
Atomic values modification in relaxed order
假设我有以下代码片段:
std::atomic<int> a(0);
void thread1()
{
int x = a.fetch_add(1, std::memory_order_relaxed);
std::cout << x << std::endl;
}
void thread2()
{
int x = a.fetch_add(1, std::memory_order_relaxed);
std::cout << x << std::endl;
}
int main()
{
std::thread t1(thread1);
std::thread t2(thread2);
t1.join();
t2.join();
}
问题是:结果能得到0 0
吗?
这里两个线程都以松散的内存顺序读取和修改a
,所以看起来它们都可以看到a
的零值。但实际上我只看到 0 1
或 1 0
.
不,0 0
不可能。宽松的内存顺序并不意味着操作不是原子的,0 0
发生的唯一方法是读取-修改-写入是非原子的。但是由于 std::atomic::fetch_add
是原子操作的,我们知道一次只有一个 fetch_add
可能在操作,所以只有 0 1
或 1 0
是可能的。
假设我有以下代码片段:
std::atomic<int> a(0);
void thread1()
{
int x = a.fetch_add(1, std::memory_order_relaxed);
std::cout << x << std::endl;
}
void thread2()
{
int x = a.fetch_add(1, std::memory_order_relaxed);
std::cout << x << std::endl;
}
int main()
{
std::thread t1(thread1);
std::thread t2(thread2);
t1.join();
t2.join();
}
问题是:结果能得到0 0
吗?
这里两个线程都以松散的内存顺序读取和修改a
,所以看起来它们都可以看到a
的零值。但实际上我只看到 0 1
或 1 0
.
不,0 0
不可能。宽松的内存顺序并不意味着操作不是原子的,0 0
发生的唯一方法是读取-修改-写入是非原子的。但是由于 std::atomic::fetch_add
是原子操作的,我们知道一次只有一个 fetch_add
可能在操作,所以只有 0 1
或 1 0
是可能的。