简述
C++11中加入了头文件,此头文件主要声明了std::thread线程类。C++11的标准类std::thread对线程进行了封装。
C++11所定义的线程是和操作系统的线程一一对应的,也就是说我们生成的线程都是直接接受操作系统的调度的,一个进程所能创建的线程数目以及一个操作系统所能创建的总的线程数据等都由运行时操作系统限定。
Thread
std::thread(class)
生成单个可执行线程,可以在多线程环境中与其他线程并发执行,同时共享相同的地址空间。初始化的线程对象拥有唯一的线程id,状态为joinable;未初始化的线程对象状态为non-joinabe,与其他non-joinable的线程对象共用通用的线程id。线程对象从joinable到non-joinable有以下两种途径:1)通过move被转移; 2)线程调用join或者detach函数。
线程构造(constructor)
std::thread 构造
(1). 默认构造,创建一个空的thread对象,状态non-joinable。
(2). 初始化构造,传递功能函数fn和参数args,状态joinable。创建成功线程立即启动。
(3). 拷贝构造函数(被禁用),意味着 thread 不可被拷贝构造。
(4). 移动构造,传递线程x的句柄。构造成功后x置空,等同于(1)。
实例:
#include <iostream>
#include <thread>
using namespace std;
void fun1(int n)
{
cout << "fun1 is calling" << " " << n << endl;
}
void fun2(int &n)
{
cout << "fun2 is calling" << " " << n << endl;
}
int main()
{
int n=1;
thread t1; //默认构造
thread t2(fun2, n); //初始化构造(值传递)
t2.join();
n=10;
thread t3(fun2, ref(n)); //初始化构造(引用传递)
thread t4(move(t3)); //移动构造(t4是执行线程,t3变为空线程,等同于t1)
t4.join();
return 0;
}
输出:
fun1 is calling 1
fun2 is calling 10
joinable
bool joinable() const noexcept; // 判断线程对象是否joinable
joinable:
正在执行的线程
non-joinable:
默认构造
所有权被转移(移动构造)
调用了join或者detach
实例:
#include <iostream>
#include <thread>
using namespace std;
void fun1()
{
cout << "fun1 is calling" << endl;
}
int main()
{
thread th1;
thread th2(fun1);
cout << "joinable after construction:\n";
cout << "th1: " << th1.joinable() << endl;
cout << "th2: " << th2.joinable() << endl;
if(th1.joinable())
th1.joinable();
if(th2.joinable())
th2.joinable();
cout << "joinable after joining:\n";
cout << "th1: " << th1.joinable() << '\n';
cout << "th2: " << th2.joinable() << '\n';
return 0;
}
g++ test.cpp -o test -std=c++11 -lpthread
输出:
joinable after construction:
th1: 0fun1 is calling
th2: 1
joinable after joining:
th1: 0
th2: 1
线程状态
无论在windows中还是Posix中,主线程和子线程的默认关系是:无论子线程执行完毕与否,一旦主线程(main函数)执行完毕退出,所有子线程执行都会终止。这时整个进程结束或僵死,部分线程保持一种终止执行但还未销毁的状态,而进程必须在其所有线程销毁后销毁,这时进程处于僵死状态。线程函数执行完毕退出,或以其他非常方式终止,线程进入终止态,但是为线程分配的系统资源不一定释放,可能在系统重启之前,一直都不能释放,终止态的线程,仍旧作为一个线程实体存在于操作系统中,什么时候销毁,取决于线程属性。在这种情况下,主线程和子线程通常定义以下两种关系:
1、可会合(joinable):这种关系下,主线程需要明确执行等待操作,在子线程结束后,主线程的等待操作执行完毕,子线程和主线程会合,这时主线程继续执行等待操作之后的下一步操作。主线程必须会合可会合的子线程。在主线程的线程函数内部调用子线程对象的wait函数实现,即使子线