一、引入线程库<thread>,提供了thread类,创建一个线程即实例化一个该类的对象。
#include<thread>
二、创建线程与线程拷贝
一个线程可以用一个 thread 类的对象来表示
#include<iostream>
#include<thread>
using namespace std;
void test()
{
cout << "thread_funa()" << endl;
}
int main()
{
//创建线程——构造函数
thread threadOne(test);
//输出线程id
cout << threadOne.get_id() << endl;
//移动拷贝构造
thread threadTow(std::move(threadOne));
cout << threadTow.get_id() << endl;
threadTow.join();
//移动拷贝构造进行资源的交换,所有要注释掉
//threadOne.join();
}
注:thread对象无构造函数,不能先构造thread对象再进行拷贝。
三、线程的使用
thread类提供了以下成员函数
成员函数 | 作用 |
get_id() | 获取当前thread对象的线程id |
joinable() | 判断当前线程是否活跃(是:true;否:false)即是否支持调用 join() |
join() | 阻塞当前thread 对象所在的线程,直至thread 对象表示的线程执行完毕 |
detach() | *将当前线程从调用该函数的线程中分离出去,他们彼此独立运行 |
swap() | 交换两个线程的状态 |
注意:每个thread 对象在调用析构销毁前,要么调用 join() 函数令主线程等待子线程执行完毕,要么调用detach() 函数将子线程和主线程分离,二者必选一,否则存在以下问题:
- 线程占用的资源无法全部释放,造成内存泄露
- 当主线程执行完毕而子线程未完时,程序执行引发异常
#include<iostream>
#include<thread>
using namespace std;
void test()
{
sleep(100);
cout << "************" << endl;
}
int main()
{
//创建线程——构造函数
thread a(test);
cout << a.get_id() << endl;
// 将a线程与主线程分离开分别独立运行
a.detach();
}
四、this_thread 命名空间的部分函数
函数 | 作用 |
yield() | 阻塞当前线程让出cpu,直至条件成熟 |
sleep_for() | 阻塞当前线程指定的时间 |
sleep_until() | 阻塞当前线程,直至某个时间点为止 |
//休眠1000毫秒,1s
this_thread::sleep_for(chrono::milliseconds(1000));
五、互斥锁,实现线程同步(避免并发异常)
互斥锁用 mutex 类(位于std命名空间中)的对象表示,#include<mutex>
解释:lock()是加锁,unlock()解锁
#include<mutex>
using namespcase std;
mutex m; //实例化mutex对象m
int a = 0;
void Show_n()
{
m.lock();
//为下面代码加锁
cout << a << endl;
m.unlock();
}