我最近问“抛出的对象不能在多线程解决方案中被捕获”并得到了完美的正确答案。但是,我仍然很困惑为什么只有一个线程执行写操作时会出现竞争条件。让我粘贴原始有问题的代码:
#include <iostream>
#include <thread>
using namespace std;
struct solution_using_thread {
solution_using_thread()
: alive_(true), thread_() {
thread_ = thread([this]() {
while(alive_);
});
}
~solution_using_thread() {
alive_ = false;
thread_.join();
}
private:
bool alive_;
thread thread_;
};
int main() {
cout << 0 << endl;
try {
solution_using_thread solution;
throw 1;
} catch (int i ) {
cout << i << endl;
}
cout << 2 << endl;
}
有时输出只是
0
根据链接的问题,如果我改为使用 member atomic<bool> alive_
,则输出变为预期
0
1
2
现在,我试图解释为什么成员bool alive_
会导致未定义的行为。
案例1(快乐结局):
- 变量
solution
被初始化:solution_using_thread
的默认构造函数在主线程中设置alive_
为。true
- 线程启动并且 的值
alive_
恰好true
在第二个线程中。所以线程执行卡在while
循环中。 - 在构造函数返回之前,第二个线程已经启动。
- 我们
throw 1
。- 的析构函数
solution
被调用。的值alive_
在true
主线程中。 thread.join()
阻塞,直到 的值alive_
与第二个线程同步。- 在同步了一些有限的延迟之后
alive_
,while 循环终止,第二个线程结束,thread_.join()
返回和堆栈展开愉快地完成。
- 的析构函数
- 输出是
0 1 2
情况 2(不需要,但至少不是“未定义行为”):
- 变量
solution
被初始化:solution_using_thread
的默认构造函数在主线程中设置alive_
为。true
- 线程启动并且 的值
alive_
恰好false
在第二个线程中。所以线程执行立即结束。 - 在构造函数返回之前,第二个线程已经启动。
- 我们
throw 1
thread.join()
立即返回,因为线程已经完成。
- 输出是
0 1 2
显然,至少还有一种情况,它只打印0
. 你能描述一下那个案例吗?