C++多线程和detach相对的函数有join,join的意思是父线程等待子线程结束,而detach的含义是主线程和子线程相互分离,互不干扰,这样看起来没什么问题,但是在某些条件下需要特别谨慎。
例如当子线程中有while循环时,如果主线程退出,进程结束,子线程也会退出,但是子线程中申请的资源不一定会释放。请看如下例子:
使用join
#include <iostream>
#include <thread>
#include <windows.h>
#include <fstream>
void *childThread(void *arg);
using namespace std;
class Resource {
public:
Resource(int n) {
this->n_ = n;
fstream outfile(".\\out.txt", ios::app);
if (!outfile.is_open())
{
std::cout << "Can not open file" << std::endl;
}
outfile << "Create Resource." << endl;
outfile.close();
}
virtual ~Resource() {
fstream outfile(".\\out.txt", ios::app);
if (!outfile.is_open())
{
std::cout << "Can not open file" << std::endl;
}
outfile << "free Resource." << endl;
outfile.close();
}
private:
int n_;
};
int main(int argc, char **argv) {
std::thread t1 = std::thread(childThread, nullptr);
Sleep(1000);
t1.join();
return 0;
}
void *childThread(void *arg) {
Resource r(5);
while (true) {
Sleep(60 * 1000);
}
return nullptr;
}
主线程一直等待子线程结束,而子线程是一个while循环,程序一直等待,正常。
使用detach
#include <iostream>
#include <thread>
#include <windows.h>
#include <fstream>
void *childThread(void *arg);
using namespace std;
class Resource {
public:
Resource(int n) {
this->n_ = n;
fstream outfile(".\\out.txt", ios::app);
if (!outfile.is_open())
{
std::cout << "Can not open file" << std::endl;
}
outfile << "Create Resource." << endl;
outfile.close();
}
virtual ~Resource() {
fstream outfile(".\\out.txt", ios::app);
if (!outfile.is_open())
{
std::cout << "Can not open file" << std::endl;
}
outfile << "free Resource." << endl;
outfile.close();
}
private:
int n_;
};
int main(int argc, char **argv) {
std::thread t1 = std::thread(childThread, nullptr);
Sleep(1000);
t1.detach();
return 0;
}
void *childThread(void *arg) {
Resource r(5);
while (true) {
Sleep(60 * 1000);
}
return nullptr;
}
请看使用detach后,进程可以退出,不会卡住,但是out.txe文件中只有"Create Resource."没有 "free Resource.",说明定义的变量r没有析构,可能存在资源未释放的情况。
代码稍加修改如下:
#include <iostream>
#include <thread>
#include <windows.h>
#include <fstream>
void *childThread(void *arg);
using namespace std;
class Resource {
public:
Resource(int n) {
this->n_ = n;
fstream outfile(".\\out.txt", ios::app);
if (!outfile.is_open())
{
std::cout << "Can not open file" << std::endl;
}
outfile << "Create Resource." << endl;
outfile.close();
}
virtual ~Resource() {
fstream outfile(".\\out.txt", ios::app);
if (!outfile.is_open())
{
std::cout << "Can not open file" << std::endl;
}
outfile << "free Resource." << endl;
outfile.close();
}
private:
int n_;
};
int main(int argc, char **argv) {
std::thread t1 = std::thread(childThread, nullptr);
Sleep(5000);
t1.detach();
return 0;
}
void *childThread(void *arg) {
Resource r(5);
Sleep(3000);
return nullptr;
}
因为子线程sleep3秒,主线程sleep 5秒,所以定义的变量r的构造和析构打印都有,简言之,用detach需要特别谨慎,避免有资源未释放情况发生。