线程加入问题

Kol*_*nya 4 c++ multithreading thread-safety c++11

我正在阅读一些关于线程的手册,我想到他们展示的代码并不安全:

std::cout << "starting first helper...\n";
std::thread helper1(foo);

std::cout << "starting second helper...\n";
std::thread helper2(bar);

std::cout << "waiting for helpers to finish..." << std::endl;
helper1.join();   // #1 NOT SAFE
helper2.join();   // #2 NOT SAFE
Run Code Online (Sandbox Code Playgroud)

我相信这段代码并不是绝对安全的.如果我没有误会,当控制到达标记为和的行时,无法保证helper1并且helper2已经处于可连接状态.线程仍然无法启动,此时没有任何ID.这将导致未被捕获的异常被抛出#1#2std::thread::join()

我认为以下代码解决了这个问题.我对吗?

std::cout << "starting first helper...\n";
std::thread helper1(foo);

std::cout << "starting second helper...\n";
std::thread helper2(bar);

std::cout << "waiting for helpers to finish..." << std::endl;
while ( helper1.joinable() == false ) { }
helper1.join();   // #1 SAFE
while ( helper2.joinable() == false ) { }
helper2.join();   // #2 SAFE
Run Code Online (Sandbox Code Playgroud)

Yak*_*ont 5

一个std::threadjoinable如果它包含尚未线程状态join编或detatch编着.

A std::thread通过非默认构造获得线程状态,或者move从另一个构建一个线程状态std::thread.move编辑时它会丢失它.

构造完成后获得线程状态没有延迟.当线程函数完成时它不会消失.所以没有那个问题.

有一个问题是,如果代码抛出上面,你将无法joindetatch在程序关闭时导致坏消息.总是std::thread用RAII包装器来包装以避免这种情况,或者只是使用std::async它返回voidstd::future同样地包装结果(因为标准说它在dtor中阻塞,但是microsofts实现没有,所以你不能相信它是否会).