本文讨论C++11 中如何创建和使用多线程,以及如何解决资源进程、数据同步等问题。
C++ 11 多线程
创建和使用线程
在C ++ 11中,我们可以通过创建std :: thread类的对象来创建其他线程。每个std :: thread 对象都可以与一个线程关联。
-
三种方式创建线程
可以在thread对象上附加一个回调,该回调将在新线程启动时执行。这些回调可以是函数指针、函数对象、Lambda函数。
新线程将在创建新thread对象后立即启动,并将与启动它的线程并行执行传递的回调。而且,任何线程都可以通过在该线程的对象上调用 join() 函数来等待另一个线程退出。//普通函数 void threadFunc(){ for (int i = 0; i < 1000; i++) { printf("FuncPointer %d\n", i); } return; } //Lambda函数 auto LambdaFunc = [](){ for (int i = 0; i < 1000; i++){ printf("Lambda %d\n", i); } }; //仿函数回调 class OBJFunc { public: void operator() (){ for (int i = 0; i < 1000; i++){ printf("Object %d\n", i); } } }objFunc; int main(){ thread FuncThread(threadFunc); thread LambdaThread(LambdaFunc); thread ObjThread(objFunc); LambdaThread.join(); FuncThread.join(); ObjThread.join(); return 0; }
-
区分不同的线程
每个thread对象都有一个关联的ID,我们可以使用成员函数获取相关线程对象的ID,也可以获取当前线程使用的ID。
std::thread::get_id() //成员函数的id std::this_thread::get_id() //当前线程的id
void threadFunc(){ printf("threadFunc id= %d\n", this_thread::get_id()); _sleep(1000); cout << "threadFunc return" << endl; return; } int main(){ printf("Main() id= %d\n", this_thread::get_id()); thread FuncThread(threadFunc); printf("FuncThread.get_id() = %d\n", FuncThread.get_id()); FuncThread.join(); return 0; }
连接和分离线程
通过调用join()
成员函数,可以另一个线程等待另外一个线程。它会造成堵塞直至该thread 对象结束。
通过调用detach()
成员函数,可以实现进程分离,分离的进程也称为守护进程或后台进程。调用detach() 之后,thread对象不再与实际的执行线程关联。
-
注意事项1:不要在已结束的线程对象上调用
join()
或detach
,否则将会导致程序终止。因此,在调用join()
或detach()
之前,我们应该使用joinable()
成员函数检查线程是否可连接。thread FuncThread(threadFunc); FuncThread.join(); if (FuncThread.joinable()){ FuncThread.join();