学习C ++多线程
在我的示例中,线程helper1
和helper2
在main
线程完成之前已完成执行。但是,程序崩溃了。我特别指出了.join()
语句,看看程序如何表现,期待没有错误,因为main()
在其他两个线程完成后调用std::terminate
。
void foo()
{
// simulate expensive operation
std::this_thread::sleep_for(std::chrono::seconds(5));
std::cout << "t1\n";
}
void bar()
{
// simulate expensive operation
std::this_thread::sleep_for(std::chrono::seconds(1));
std::cout << "t2\n";
}
int main()
{
std::cout << "starting first helper...\n";
std::thread helper1(foo);
std::cout << "starting second helper...\n";
std::thread helper2(bar);
std::this_thread::sleep_for(std::chrono::seconds(10));
std::cout << "waiting for helpers to finish..." << std::endl;
//helper1.join();
//helper2.join();
std::cout << "done!\n";
}
答案 0 :(得分:6)
我说你的问题没有意义,因为它是基于错误的假设。了解 线程已完成的唯一方法是线程的join()
返回。在join()
返回之前,并不是&#34;线程已经完成&#34;。可能确实线程执行中的某些语句已经完成(例如,打印消息,或者更好,写入原子变量),但是线程函数本身的完成不是可测量的以任何其他方式加入。
所以 none 线程&#34;已完成&#34;直到你加入他们。
答案 1 :(得分:4)
如果关联线程仍可加入,std::~thread
会调用terminate
:
30.3.1.3 thread destructor [thread.thread.destr]
~thread();
如果
joinable()
,请致电std::terminate()
。否则,没有任何影响。 [ 注意:隐式分离或连接其析构函数中的joinable()
线程可能导致难以调试正确性(对于分离)或性能(对于连接)仅在引发异常时遇到的错误。因此,程序员必须确保在线程仍可连接时永远不会执行析构函数。 - 后注]
您需要致电.detach()
或.join()
。除此之外,由于您无法确定操作系统如何安排线程,您最终可能会以任何方式中断线程,因此最好从一开始就使用.join()
。
答案 2 :(得分:4)
基于reference,必须在调用析构函数时加入或分离底层线程。退出main
时会调用析构函数,并可能假定已调用join
或detach
。
代码也不应该崩溃,只要在构造helper1
和helper2
之后的某个地方有以下两行。
helper1.detach()
helper2.detach()
答案 3 :(得分:3)
CPU可以按任意顺序安排三个线程(main
/ thread1
/ thread2
)。可能会发生main
没有时间运行并且线程退出的情况。因此,您需要在join
中保持main
以处理此案例。除非您使用RTOS
。