之前写代码的时候,忘记写join(),结果进程崩溃了。
这篇文章记录一下join()的必要性。
环境
Virutal Studio 2022
无join()和detach()
#include <iostream>
#include <mutex>
static bool bRunning = true;
static bool bdata = true;
std::mutex mtx;
void _func(void)
{
do{
std::unique_lock<std::mutex> ulk(mtx);
std::cout << std::this_thread::get_id() << std::endl;
} while (bRunning);
}
int main()
{
std::thread th(_func);
while (bRunning)
{
std::lock_guard<std::mutex> lg(mtx);
std::cout << std::this_thread::get_id() << std::endl;
bRunning = false;
}
//th.detach();
//th.join();
return 0;
}
运行结果
程序崩溃。如果在debug模式下,会弹出以下弹窗
join
代码修改为:
int main()
{
std::thread th(_func);
while (bRunning)
{
std::lock_guard<std::mutex> lg(mtx);
std::cout << std::this_thread::get_id() << std::endl;
bRunning = false;
}
//th.detach();
th.join();
return 0;
}
运行结果
程序正常退出
detach
代码修改为:
int main()
{
std::thread th(_func);
while (bRunning)
{
std::lock_guard<std::mutex> lg(mtx);
std::cout << std::this_thread::get_id() << std::endl;
bRunning = false;
}
th.detach();
//th.join();
return 0;
}
运行结果
程序正常退出
原因分析
试验一
这里我怀疑是,主线程在要结束时,子线程还没有结束,没有指定线程的join或者detach运行方式,导致了错误。
在做一个试验,同样不指定join或者detach,但是让子线程sleep 1s,主线程 sleep 3s,看看会报错吗?
#include <iostream>
#include <thread>
#include <Windows.h>
void _func(void)
{
Sleep(1000);
std::cout << "child thread:" << std::this_thread::get_id() << std::endl;
}
int main()
{
std::thread th(_func);
Sleep(3000);
std::cout << "father thread:" << std::this_thread::get_id() << std::endl;
//th.detach();
//th.join();
return 0;
}
结果
依然会有上面提到的 debug error 弹窗。
所以和子线程函数是不是执行完了没关系。
找资料
在cplusplus.com/reference中,join()和detach()中都提到了,需要调用这两个函数之一,才能安全的销毁。
cplusplus-join
cplusplus-detach
After a call to this function, the thread object becomes non-joinable and can be destroyed safely.