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();
}
运行结果: