这是一个基于代码的最小示例:
// Example program
#include <iostream>
#include <string>
#include <thread>
int main()
{
std::cout << "Start main\n";
int i = 0;
auto some_thread = std::thread([&]() {
std::cout << "Start some thread\n";
while(i++ < 100) {
std::cout << i << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
}
});
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
auto some_thread2 = std::thread([&]() {
std::cout << "Start thread 2\n";
if (some_thread.joinable()) {
std::cout << "Thread 2 will join\n";
some_thread.join();
std::cout << "Thread 2 ended\n";
} else {
std::cout << "Thread 2 ended but didn't join\n";
}
});
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
if (some_thread.joinable()) {
std::cout << "Main will join\n";
some_thread.join();
std::cout << "Main ended\n";
return 0;
} else {
std::cout << "Main ended but didn't join\n";
return 1;
}
}
简而言之,完整程序(如本例所示)从不同的线程访问某些std::thread
对象,并尝试join
和detach
。
我知道这是一个糟糕的设计,并且如果你尝试加入一个线程两次它会崩溃,因为在第一个完成之后,那么没有与之关联的线程。但事实并非如此。
在此示例中,它在线程结束之前崩溃并且使用Abort trap:6
。它只打印几个数字然后崩溃(线程不会结束它的执行)。
代码不是我的,我不想重新设计。我只想了解它为什么会崩溃。
最后一点,原始代码以某种方式使用信号量等工作(虽然有一些随机崩溃)。
答案 0 :(得分:0)
我知道......如果你尝试加入一个线程两次,它会崩溃,因为在第一个完成之后,就没有与之关联的线程了。但事实并非如此。
恰恰相反,这正是这里发生的事情。 some_thread2
调用some_thread.join()
,当等待some_thread
退出时,主线程也在调用some_thread.join()
。 some_thread
仍处于活动状态,并且在两次检查时尚未加入,因此joinable()
在两种情况下均返回true。
避免崩溃的一种方法是在主线程中检查some_thread2.join();
之前添加some_thread.joinable()
(但如果这样做,主线程就不需要加入some_thread
})。
在任何情况下,都不清楚为什么要从两个不同的线程join
线程,所以很难建议更好的解决方案。
答案 1 :(得分:0)
std :: thread库通常在支持pthreads的环境中的pthreads之上实现(例如:libstdc ++)。
引自pthread_join
linux documentation:
如果多个线程同时尝试使用同一个线程加入, 结果未定义。
它还提到它返回以下错误:
EINVAL另一个线程已经在等待加入此线程。