具有这样简单的代码:
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
函数不是在等待线程完成吗?
答案 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
。这样,线程在破坏时就无法加入。