【发布时间】:2023-03-20 14:33:02
【问题描述】:
c++ atomics 竞争条件 我正在学习 c++ atomics。所以我故意制造了一个竞争条件。你可以看到我的 void add 函数将 x 增加 1 打印 x 的值和增加它的线程名称。两个线程 t1 和 t2 可以访问 void add 函数。所以这是一个竞争条件,我得到的输出类似于 1,1 1,2(最佳情况)2,2 和 2,1。我的问题是 2,1 输出是如何可能的。请任何人帮忙。
#include <iostream>
#include<thread>
#include<atomic>
using namespace std;
int x = 0;
std::atomic<int>s{ 0 };
void add(const char* c) {
++x;
cout<< c << endl << x << endl;
}
int main() {
std::thread t1(add,"t1");
std::thread t2(add,"t2");
t1.join();
t2.join();
cin.get();
}
【问题讨论】:
-
有一个常见的误解,认为“原子”意味着“线程安全,我可以在任何线程中以任何我想要的方式访问这个变量,我总是会得到我认为正确的结果”。这不是真的。 P.S.:显示的代码甚至没有使用原子变量,它完全没有使用。
-
@RichardCritten:这不是真的,例如任何时候你的进程的输出取决于它的一些线程的时间你有一个竞争条件。这并不意味着相应的 C++ 程序会调用未定义的行为。竞争条件和数据竞争不是一回事。一个例子:如果我启动两个线程都打印它们的 ID,我创建了一个竞争条件,但既不是数据竞争也不是未定义的行为。
-
@Peter 请参阅上面 cppreference 的报价 - 我会寻找标准报价。
-
您的问题混淆了两个不相关的问题。首先,编写的代码表现出未定义的行为,通过在两个没有同步的线程中更新非原子对象
x。任何事情都允许发生。其次,即使将x替换为s从而避免未定义的行为,程序也是不确定的:线程t1可以在t2启动之前完成,或者t2可以在t1启动之前完成,或者两者可以交错(例如,一个线程执行增量,然后另一个执行增量,然后它们打印相同的值2)。 -
根据 C++ 标准,是的,这是未定义的行为。在实践中,程序行为可能由使用的实现定义(仅由非原子读/写)。问题是你没有同步
std::cout的使用,因此<<的效果可能会以任何方式交错。
标签: c++ atomic race-condition