【发布时间】:2015-03-03 08:16:26
【问题描述】:
我最近问过“Thrown object cannot be caught in a multi-threaded solution”并得到了完美的正确答案。但是,我仍然很困惑为什么只有一个线程执行写操作时会出现竞争条件。我贴一下原来有问题的代码:
#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
根据链接的问题,如果我改为使用成员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。你能描述一下那个案例吗?
【问题讨论】:
-
一般规则:不要试图理解未定义的行为。绝对不要试图猜测和“解决”它。 Recommended video
标签: exception c++11 race-condition raii stdatomic