c++ 11 之后有了标准的线程库:std::thread。
参考thread库的使用
构造函数
thread的构造函数有下面四个重载
默认构造函数
thread() noexcept
初始化构造函数
template <class Fn, class... Args>
explicit thread (Fn&& fn, Args&&... args);
该函数使用可变参数模板来构造一个线程对象,用来代表一个新的可join的执行线程。这个执行线程通过可变参数传入线程函数对象fn,以及函数的参数列表(可以简单理解为通过传值的方式将参数传给该构造函数)
拷贝构造函数
thread (const thread&) = delete;
线程不支持拷贝构造
移动构造
thread(thread&&x) noexcept;
转移参数x所代表的可执行指令的所有权,而不会影响线程的执行,转移后,参数x不再代表任何执行线程。
析构函数
析构函数用于销毁线程,如果这个线程是可以join的,那么析构函数会调用terminate()函数来终止线程。在thread对象被销毁之前应该尽可能将其join或者detach,以防止执行线程因为对象销毁而终止。
#include<iostream>
#include<thread>
#include<unistd.h>
using namespace std;
void printtHelloWorld(){
while(true){
cout<<"hello world"<<endl;
sleep(1);
}
}
int main(){
thread t1(printtHelloWorld);
sleep(3);
t1.~thread();
return 0;
}
operator=
thread& operator= (thread&& rhs) noexcept;
thread& operator= (const thread&) = delete;
thread对象不允许拷贝构造,同样的对于赋值操作符的重载实质是移动赋值。
#include<iostream>
#include<thread>
using namespace std;
void printHelloWorld(){
cout<<"Hello World!"<<endl;
}
int main(){
thread t1;
t1 = thread(printHelloWorld);
t1.join();
return 0;
}
编译g++ test.cpp -std=c++11 -lpthread - o test
joinable
如果thread对象代表了一个执行线程,那么可以joinable。
C++中有几种情况不能joinable
- 默认构造
- 执行过move操作
- 执行过join或者detach
#include<iostream>
#include<thread>
using namespace std;
void printHelloWorld(){
cout<<"Hello World!"<<endl;
}
int main(){
thread t1;
if(!t1.joinable()){
cout<<"Thread is not joinable! (default constructor)"<<endl;
}
t1 = thread(printHelloWorld);
if(t1.joinable()){
cout<<"Thread is joinable! (represents a thread of execution)"<<endl;
t1.join();
if(!t1.joinable()){
cout<<"Thread is not joinable! (after call join())"<<endl;
}
}
thread t3;
thread t2(printHelloWorld);
t3 = move(t2);
if(!t2.joinable()){
cout<<"Thread is not joinable! (after move)"<<endl;
}
t3.join();
return 0;
}
Thread is not joinable! (default constructor)
Thread is joinable! (represents a thread of execution)
Hello World!
Thread is not joinable! (after call join())
Thread is not joinable! (after move)
Hello World!
join
线程执行完毕后函数返回,join函数可以用来阻塞调用此函数的线程,调用这个函数之后,线程对象将变成非joinable并且可以被安全销毁。
#include<iostream>
#include<thread>
#include<unistd.h>
using namespace std;
void pauseThread(int n){
sleep(n);
std::cout<<"pause of "<<n<<" seconds ended"<<std::endl;
}
int main(){
cout<<"spawing 3 threads..."<<endl;
std::thread t1(pauseThread,1);
std::thread t2(pauseThread,2);
std::thread t3(pauseThread,3);
cout<<"Done spawning threads. Now wait for them to join: "<<endl;
t1.join();
t2.join();
t3.join();
cout<<"All threads joined!"<<endl;
return 0;
}
detach
这个函数会将执行线程与调用线程分离,允许它们彼此独立运行,任意一个线程结束之后会释放拥有的资源。调用之后,线程对象会变成非joinable并且可以安全销毁。
#include<iostream>
#include<thread>
#include<unistd.h>
using namespace std;
void pauseThread(int n){
this_thread::sleep_for(chrono::seconds(n));
std::cout<<"pause of "<<n<<" seconds ended"<<std::endl;
}
int main(){
cout<<"spawing 3 threads..."<<endl;
std::thread (pauseThread,1).detach();
std::thread (pauseThread,2).detach();
std::thread (pauseThread,3).detach();
cout<<"Done spawning threads. (the main thread will now pause for 5 seconds)"<<endl;
pauseThread(5);
return 0;
}