1、启动线程存在的固有开销
1. OS分配内核资源、堆栈空间
2. 将线程加入调度器
2、每个线程都需要一份独立的堆栈空间
对于32位系统,一个线程占用1MB的栈空间
3、线程间的任务调度,OS需要做上下文切换
因此,1. 线程启动后,需要关注其销毁
2. 系统资源有些,需要考虑启动线程的数量是否合适
1、启动线程,主线程抛异常,异常退出
例子:
#include#include using namespace std; struct func { func(int& i) : i(i) {} void operator()() const { cout << typeid(*this).name() << " " << __func__ << ": " << __LINE__ << " i: " << i << endl; } private: int& i; }; int main(int argc, char const *argv[]) { int i = 1; func f(i); thread t(f); // 主线程抛异常退出 cout << "throw exception start: " << endl; throw std::runtime_error("unknown error!!!!!!!!!!"); return 0; }
代码中主线程抛异常,提前退出,线程对象t不会调用析构函数销毁线程资源,会导致系统资源泄露。
2、主线程不等待线程退出,先结束执行
int main(int argc, char const *argv[])
{
int i = 1;
func f(i);
thread t(f);
return 0;
}
代码中主线程提前退出,线程对象t调用析构函数提前销毁线程资源,线程执行异常。
三、thread使用防护需保证主线程退出前等待线程退出(join)或线程已逃逸主线程(detach)
方法一:使用try-catch捕获异常进行防护
int main(int argc, char const *argv[])
{
int i = 1;
func f(i);
thread t(f);
try
{
cout << "throw exception start: " << endl;
throw std::runtime_error("unknown error!!!!!!!!!!");
}
catch(const std::exception& e)
{
std::cerr << e.what() << 'n';
t.join();
}
return 0;
}
方法二:利用RAII机制
#include#include using namespace std; struct func { func(int& i) : i(i) {} void operator()() const { cout << typeid(*this).name() << " " << __func__ << ": " << __LINE__ << " i: " << i << endl; } private: int i; }; struct thread_guard { thread_guard(thread& t) : t_(t) {} ~thread_guard() { if (t_.joinable()) { t_.join(); } } thread_guard(const thread_guard& ) = delete; thread_guard& operator=(const thread_guard& ) = delete; private: thread& t_; }; int main(int argc, char const *argv[]) { int i = 1; func f(i); thread t(f); thread_guard tg(t); cout << "start throw exception....." << endl; throw std::runtime_error("unknown===================="); return 0; }



