1. 语法
头文件为<thread>
thread是一个线程类,可以用来生成对象并运行该线程 thread t1(function)
此时子线程t1
依附于主线程,主线程结束后子线程也会结束
t1.join()
让主线程等待子线程结束后再继续运行
t1.detach()
分离主线程与子线程,主线程结束后子线程依然可以运行
this_thread::get_id()
查询当前线程id
2. 对象作为线程参数
thread t1(function, A(1))
类A生成一个临时对象传入线程中,此时会在主线程内调用默认构造、拷贝构造、析构函数。若子线程以
引用方式接受对象,则在子线程中只调用一次析构函数。
thread t1(function, 1)
将1作为参数传入线程,则会在子线程中调用默认构造函数与析构函数,此时如果没有调用join()
函数,很
可能主线程提前结束,子线程无法调用构造函数导致出错。
A aa(1); thread t1(function, aa)
将主线程中构造的对象传入线程,则首先会在主线程中调用默认构造函数构建aa,接着在主线程
中调用拷贝构造函数将aa拷入子线程,并在子线程中执行析构函数,最后在主线程中执行析构函数回收aa。
注意:以上例子默认使用引用传递,若是值传递,则在子线程中会增加一次拷贝构造函数调用
虽然形式上以引用方式传递,但还是会调用拷贝构造函数,所以子线程中的对象地址和主线程的不同
若想要真正的实现引用传递,需使用ref()
函数,如A aa(1); thread t1(function, ref(aa))
注意:ref()
函数不能作用于临时对象,因为临时对象在使用后会被销毁
如果想要更改const
类型的对象数据,可在对象的成员数据前加mutable
关键字
3. 用成员函数指针做线程函数
thread mythread(&A::C, aa, 4);
C为类A中成员函数,aa为A的对象,C有一个参数为4。
此时会在主线程中执行一次拷贝构造函数将aa拷贝至子线程,在子线程中执行析构函数
thread mythread(&A::C, ref(aa), 4)
==thread mythread(&A::C, &aa, 4)
上面两个语句效果相同,均不需要在主线程中调用拷贝构造函数,做到了真正的引用传递
注意:没有在主线程中调用拷贝构造函数,必须用join()
函数,因为主线程结束后无法调用拷贝构造
4. 智能指针作为参数传递
void myprint (unique_ptr<int> p) {}
thread mythread(myprint, move(p1));
智能指针传递到子进程后,p关联了p1之前关联的指针,p1的指针转移到了p上,p1不关联指针
5. 创建和等待多个线程
创建多个线程,使用容器来存放线程,线程的入口统一使用myprint
函数
void myprint (int i) {
cout << "这里是子线程" << ", id是" << std::this_thread::get_id() << endl;
}
int main()
{
vector<thread> mythread;
for (int i = 0; i < 10; ++i) {
mythread.push_back(thread(myprint, i));
}
for (auto it = mythread.begin(); it != mythread.end(); ++it) {
it->join();
}
cout << "hello world!" << endl;
return 0;
}
运行的结果是乱序的,这与操作系统内部对线程的运行调度机制有关
![](https://secure2.wostatic.cn/static/nFAGHnycmaFghmSgtZKzJr/image.png)
**数据共享问题**
有读有写的数据:读的时候不能写,写的时候不能读
只读的数据:是安全稳定的,可以直接读取
测试代码
#include <iostream>
#include <thread>
#include <vector>
#include <memory>
using namespace std;
class A {
public:
A(int a) : m_a(a) {
cout << "在线程id:" << std::this_thread::get_id() << "中 执行默认构造函数" << endl;
}
A(const A& B) {
m_a = B.m_a;
cout << "在线程id:" << std::this_thread::get_id() << "中 执行拷贝构造函数" << endl;
}
void C(int c) {
cout << "在线程id:" << std::this_thread::get_id() << "中 调用函数C" << endl;
}
void operator() (int k) {
cout << "在线程id:" << std::this_thread::get_id() << "中 实现了小括号重载" << endl;
}
~A() {
cout << "在线程id:" << std::this_thread::get_id() << "中 执行析构函数" << endl;
}
mutable int m_a;
};
void myprint (int i) {
cout << "这里是子线程" << ", id是" << std::this_thread::get_id() << endl;
}
int main()
{
vector<thread> mythread;
for (int i = 0; i < 10; ++i) {
mythread.push_back(thread(myprint, i));
}
for (auto it = mythread.begin(); it != mythread.end(); ++it) {
it->join();
}
cout << "hello world!" << endl;
return 0;
}