抛出的对象无法在多线程解决方案中捕获

时间:2015-03-02 14:09:10

标签: exception c++11 constructor raii stdthread

我有一个RAII类来解决内部线程中的问题:

#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

总是应该是:

0
1
2

coliru中,它始终只有0

我在这里缺少什么?

PS:抱歉,这个含糊不清的标题。请毫不犹豫地为这个问题提出更好的建议。

1 个答案:

答案 0 :(得分:1)

您假设该主题(最终)会看到alive_的更新值。但这并不能保证。没有同步的对象保证在任何有限的时间内对其他线程可见。可能alive_的值被缓存到某处并且从未更新过。

您需要一些同步才能使其工作 - 使用互斥或​​其他同步原语,或使alive_原子。这是后者的working example

#include <atomic>

struct solution_using_thread {
    solution_using_thread()
     : alive_(true), thread_() {
        thread_ = thread([this]() {
            while(alive_);
        });
    }
    ~solution_using_thread() {
        alive_ = false;
        thread_.join();
    }
private:
    atomic<bool> alive_;
    thread thread_;
};

没有任何同步,程序具有未定义的行为,因为两个线程在alive_上输入数据争用。