c++11中stl 提供了(目前)五个头文件以支持多线程:
<atomic>(提供原子操作功能)
<thread>(线程模型封装)
<mutex>(互斥量)
<condition_variable>(条件变量)
<future>
只使用win32的c++程序员可能对提供的线程库感觉很陌生。事实上,它看起来的确是pthread_xx的c++封装。
1 创建线程:
#include<iostream>
#include<thread>
void function(){
std::cout<<" in func() "<<std::endl;
return;
}
int main(){
std::thread p1(function); //创建线程
std::cout<<" in main() "<<std::endl;
p1.detach();
if(p1.joinable())
p1.join();
system("pause");
return 0;
}
关于detch( )和 join()表示线程的一种状态:
在任何一个时间点上,线程是可结合的(joinable),或者是分离的(detached)。
一个可结合的线程 (join) 能够被其他线程收回其资源和杀死;在被其他线程回收之前,它的存储器资源(如栈)是不释放的。
一个分离的线程 (detach) 是不能被其他线程回收或杀死的,它的存储器资源在它终止时由系统自动释放。
如果使用join 主线程main会等待p1线程执行完再销毁
而如果使用detach 主线程main将和p1线程分离 也就是说上述程序最后输出的顺序是不一定的
2 参数传递
#include<iostream>
#include<thread>
void function(int& a,const std::string& str){
std::cout<<a<<std::endl;
a=19;
}
int main(){
int a=5;
std::thread p1(function,a,"asdasd"); //可以传递任意数量的参数
p1.join();
std::cout<<a<<endl;
return 0;
}
尽管可以向线程函数传递任意数量的参数,但是所有的参数应当按值传递。
上例程序的输出结果为:
5
5
也就是说参数中的引用并不能起到效果
如果需要将参数按引用传递,那要向下例所示那样,必须将参数用std::ref 或者std::ref进行封装。
void function(int& a,const std::string& str){
std::cout<<a<<std::endl;
a=19;
}
int main(){
int a=5;
std::thread p1(function,std::ref(a),"asdasd"); //可以传递任意数量的参数
p1.join();
std::cout<<a<<std::endl;
return 0;
}
输出结果为
5
19
该做法涉及到内存共享 往往效率不高
3进程赋值
//将一个线程移动成另一个线程
std::thread p2=std::move(p1);
//错误做法
//std::thread p3=p1;
这里介绍一下c++11引入的 move右值引用 操作:
由图可知通过move 可以减少不必要的内存分配
在上例代码p2 = move(p1)后 p1 p2都是线程的对象
4 查看进程id以及查看系统硬件支持线程数
cout<< std::thread::hardware_concurrency() <<endl;
cout << std::this_thread::get_id <<endl;
cout<<t2.get_id<<endl; //t2为一个线程