1、線程的簡單使用
void myprint()
{
cout << "線程開始執行" << endl;
//...
cout << "線程結束執行"<< endl;
}
#include <thread>
//.....
int main()
{
thread mytobj1(myprint);//建立了一個線程,線程執行起點(入口)myprint();(2)myprint線程開始執行
mytobj1.join(); //主線程阻塞到這裡等待myprint()執行完成,當子線程執行完畢,這個join就執行完成,主線程就繼續往下執行
thread mytobj2(myprint);
mytobj2.detech(); //主線程和子線程分開執行,主線程不需要燈态子線程執行完成,可以繼續往下執行。
mytobj2.joinable(); //判斷是否可以成功使用join或者detach,傳回true(可以join或者detach)或者false(不可以join或detach)
}
(1)join() 函數
阻塞模式,主線程阻塞到這裡等待子線程函數執行完成,當子線程執行完畢,這個join就執行完成,主線程就繼續往下執行。
(2)detech()函數
非阻塞模式,主線程和子線程分開執行,主線程不需要燈态子線程執行完成,可以繼續往下執行。子線程在背景運作,相當于被C++運作時庫接管,當子線程執行完成,由運作時庫負責清理該子線程的資源。一旦detach,子線程已經被C++運作時庫接管,不能再join。
(3)joinable()函數
判斷是否可以成功使用join或者detach,傳回true(可以join或者detach)或者false(不可以join或detach).
2、其他建立線程的方法
(1)用類對象(可調用對象)
#include <iostream>
#include <thread>
class TA
{
public:
int &m_i;
TA(int &i):m_i(i)
{
std::cout << "TA ()構造函數被執行" << std::endl;
}
TA(const TA& ta):m_i(ta.m_i)
{
std::cout << "TA 拷貝構造函數被執行" << std::endl;
}
~TA()
{
std::cout << "TA 析構函數被執行" << std::endl;
}
void operator()() //不帶參數
{
//列印1
std::cout << "m_i1的值為" << m_i << std::endl;
std::cout << "m_i2的值為" << m_i << std::endl;
std::cout << "m_i3的值為" << m_i << std::endl;
std::cout << "m_i4的值為" << m_i << std::endl;
}
};
int main()
{
int myi = 6;
TA ta(myi);
std::thread mytobj2(ta); //ta:可調用對象
mytobj2.join(); //(1)等待子線程結束
//mytobj2.detach(); //(2)問題:detach主線程和子線程分開執行,當主線程執行完成後,子線程還在背景執行,
//而myi為局部變量,此時類中的列印1會出現不可預料的結果
std::cout << "Hello World!\n";
getchar();
}
源碼中(1)和(2)的執行結果如下:
主線程結束後,而ta也為局部變量,ta對象也銷毀了,為什麼子線程還可以繼續執行?
這是因為ta被複制到了子線程中去,隻要TA類對象裡沒有引用,沒有指針,那麼就不會産生問題。
(2)用lambda表達式
auto mylamthread = [] {
std::cout << "線程3開始執行了" << std::endl;
//....
std::cout << "線程3執行結束了" << std::endl;
};
int main()
{
//int myi = 6;
//TA ta(myi);
//std::thread mytobj2(ta); //ta:可調用對象
mytobj2.join(); //(1)等待子線程結束
//mytobj2.detach(); //(2)
std::thread mytobj3(mylamthread);
mytobj3.join();
std::cout << "Hello World!\n";
getchar();
}
運作結果: