等待线程完成以及将来

时间:2020-09-08 09:34:59

标签: c++

具有这样简单的代码:

void func(std::promise<int>* p) {
    int a = 10, b = 5;
    int result = a + b;
    std::cout << "From inside the Thread...." << std::endl;
    p->set_value(result);
}

int FP_main() {
    std::promise<int> p;
    std::future<int> f = p.get_future();
    std::thread th(func, &p);
    int ret = f.get();
    std::cout << "returned val: " << ret << std::endl;

    th.join();
    return 0;
}

如果仅在上面两行有join调用,为什么我们需要get函数调用? get函数不是在等待线程完成吗?

2 个答案:

答案 0 :(得分:3)

因为线程不是承诺。
承诺已完成,但线程尚未完成。

    p->set_value(result);
    // ...
    // HERE
    // ...
}

这是func的最后几行。现在,该线程将进行清理,调用析构函数等。当然,在“ HERE”中,线程可能还要进行大量其他工作-您可以在此处编写一个1小时的任务来保持线程的活动,而这与承诺无关。

这可能已经很清楚了。

最后一个有趣的地方是:

int FP_main() {
    //...
    std::thread th(func, &p);
    //...

    th.join();
    return 0;
}

'th'是局部变量。当main()返回时,将th的析构函数被调用。并且,当相关线程未完成且未加入时,该析构函数将引发异常。

如果在设置promise的值之后线程繁忙(即执行析构函数或进行一些长达1小时的工作),则在返回0后由}调用std :: thread的析构函数;会引发程序崩溃。因此,您需要加入。

答案 1 :(得分:1)

如果仅在上面两行有join调用,为什么我们需要get函数调用?

销毁 joinable std::thread对象将导致调用std::terminate()。这与它的关联线程是否完成无关。因此,在销毁可连接get()对象之前必须调用join()时,将来对std::thread的调用是无关紧要的。

如果您不想致电join(),则可以在销毁之前detach()上的某个地方致电std::thread。这样,线程在破坏时就无法加入。