一、函数方式
- thread
C++11标准线程库,创建线程:
thread mythread(函数名);
thread mythread(函数名,参数列表);
thread mythread(类对象);
- join()
mythread.join();
阻塞主线程,让主线程等待子线程执行完毕,然后和主线程回合,主线程继续向下执行。
- detach()
mythread.detach();
主线程和子线程分离,主线程和子线程同时执行,主线程不必等待子线程结束,子线程进入后台(守护线程),由运行时库接管。
- joinable()
mythread.joinable()
判断是否可以join或者detach,返回true,可以join可以detach, 返回false, 不能join不能detach
示例
#include <iostream>
#include <thread>
using namespace std;
void myprint(int n) {
cout << "我的线程开始了" << endl;
// ....
for (int i = 0; i < n; i++) {
cout << "--->子线程第" << i + 1 << "项操作。" << endl;
}
cout << "我的线程结束了" << endl;
}
int main() {
const int n = 10;
thread mythread(myprint, n);
//mythread.join(); //阻塞主线程,让主线程等待子线程执行完毕,然后和主线程回合,主线程继续向下执行。
mythread.detach(); //主线程和子线程分离,主线程和子线程同时执行,主线程不必等待子线程结束,子线程进入后台(守护线程),由运行时库接管。
/*
注意事项:detach分离后,主线程如果先结束,子线程如果还用到主线程的资源则会出错,比如引用
*/
for (int i = 0; i < n; i++) {
cout << "main thread" << endl;
}
cout << "主线程结束!" << endl;
return 0;
}
二、可执行的类对象
#include <iostream>
#include <thread>
using namespace std;
class TA {
public:
int &m_i; //bug, 一旦使用了detach,主线程先结束,引用的地址就会出现不可预料的结果,要么食用join方式,要么用拷贝(不要用引用)
TA(int &i) :m_i(i) {
cout << "constructor" << endl;
}
TA(const TA& ta) :m_i(ta.m_i) {
cout << "copy constructor" << endl;
}
~TA() {
cout << "deconstructor" << endl;
}
void operator() () {
cout << "m_i的值:" << m_i << endl;
cout << "m_i的值:" << m_i << endl;
}
};
int main() {
int i = 1;
TA ta(i);
thread mythread(ta);
//mythread.join(); //阻塞主线程,让主线程等待子线程执行完毕,然后和主线程回合,主线程继续向下执行。
mythread.detach(); //主线程和子线程分离,主线程和子线程同时执行,主线程不必等待子线程结束,子线程进入后台(守护线程),由运行时库接管。
/*
注意事项:detach分离后,主线程如果先结束,子线程如果还用到主线程的资源则会出错,比如引用
主线程结束后,ta对象会被销毁,但是不影响子线程,因为ta对象是被复制到线程中去的
*/
for (int i = 0; i < 10; i++) {
cout << "main thread" << endl;
}
cout << "主线程结束!" << endl;
return 0;
}
踩坑事项:数据最好拷贝到子线程中去,要使用引用的话,必须用join方式。
三、lamda表达式
#include <iostream>
#include <thread>
using namespace std;
int main() {
auto mylamda = [] {
cout << "lamda方式的子线程" << endl;
};
thread mythread(mylamda);
//mythread.join(); //阻塞主线程,让主线程等待子线程执行完毕,然后和主线程回合,主线程继续向下执行。
mythread.detach(); //主线程和子线程分离,主线程和子线程同时执行,主线程不必等待子线程结束,子线程进入后台(守护线程),由运行时库接管。
for (int i = 0; i < 10; i++) {
cout << "main thread" << endl;
}
cout << "主线程结束!" << endl;
return 0;
}