C++程序中启动线程的方法
C++11引入一个全新的线程库,包含启动和管理线程的工具,提供了同步(互斥、锁和原子变量)的方法,我将试图为你介绍这个全新的线程库。
如果你要编译本文中的代码,你至少需要一个支持C++11的编译器,我使用的是GCC4.6.1,需要使用-c++0x或者-c++11参数来启用C++11的支持。
启动线程
在C++11中启动一个线程是非常简单的,你可以使用std:thread来创建一个线程实例,创建完会自动启动,只需要给它传递一个要执行函数的指针即可,请看下面这个Helloworld代码:
#include<thread> #include<iostream> voidhello(){ std::cout<<"Hellofromthread"<<std::endl; } intmain(){ std::threadt1(hello); t1.join(); return0; }
所有跟线程相关的方法都在thread这个头文件中定义,比较有意思的是我们在上面的代码调用了join()函数,其目的是强迫主线程等待线程执行结束后才退出。如果你没写join()这行代码,可能执行的结果是打印了Hellofromthread和一个新行,也可能没有新行。因为主线程可能在线程执行完毕之前就返回了。
线程标识
每个线程都有一个唯一的ID以识别不同的线程,std:thread类有一个get_id()方法返回对应线程的唯一编号,你可以通过std::this_thread来访问当前线程实例,下面的例子演示如何使用这个id:
#include<thread> #include<iostream> #include<vector> voidhello(){ std::cout<<"Hellofromthread"<<std::this_thread::get_id()<<std::endl; } intmain(){ std::vector<std::thread>threads; for(inti=0;i<5;++i){ threads.push_back(std::thread(hello)); } for(auto&thread:threads){ thread.join(); } return0; }
依次启动每个线程,然后把它们保存到一个vector容器中,程序执行结果是不可预测的,例如:
Hellofromthread140276650997504 Hellofromthread140276667782912 Hellofromthread140276659390208 Hellofromthread140276642604800 Hellofromthread140276676175616
也可能是:
HellofromthreadHellofromthreadHellofromthread139810974787328Hellofromthread139810983180032Hellofromthread 139810966394624 139810991572736 139810958001920
或者其他结果,因为多个线程的执行是交错的。你完全没有办法去控制线程的执行顺序(否则那还要线程干吗?)
当线程要执行的代码就一点点,你没必要专门为之创建一个函数,你可以使用lambda来定义要执行的代码,因此第一个例子我们可以改写为:
#include<thread> #include<iostream> #include<vector> intmain(){ std::vector<std::thread>threads; for(inti=0;i<5;++i){ threads.push_back(std::thread([](){ std::cout<<"Hellofromthread"<<std::this_thread::get_id()<<std::endl; })); } for(auto&thread:threads){ thread.join(); } return0; }
在这里我们使用了一个lambda表达式替换函数指针,而结果是一样的。