C++11——多线程编程2
翻译来自https://thispointer.com//c11-multithreading-part-2-joining-and-detaching-threads/
Joining线程
线程一旦启动,另一个线程可以通过调用std::thread对象上调用join()函数等待这个线程执行完毕
std::thread th(funcPtr);
th.join();
看一个例子
主线程启动10个工作线程,启动完毕后,main函数等待他们执行完毕,joining完所有线程后,main函数继续执行
#include <iostream> #include <thread> #include <algorithm> #include <vector> #include <functional> class WorkerThread { public: void operator()() { std::cout << "Worker Thread " << std::this_thread::get_id() << "is Excecuting" << std::endl; } }; int main() { std::vector<std::thread> threadList; for (int i = 0; i < 10; i++) { threadList.push_back(std::thread(WorkerThread())); } // Now wait for all the worker thread to finish i.e. // Call join() function on each of the std::thread object std::cout << "Wait for all the worker thread to finish" << std::endl; std::for_each(threadList.begin(), threadList.end(), std::mem_fn(&std::thread::join)); std::cout << "Exiting from Main Thread" << std::endl; return 0; }
Detaching 线程
detach一个线程,需要在std::thread对象中调用std::detach()函数
std::thread th(funcPtr)
th.detach();
调用detach()后,std::thread对象不再与实际执行线程相关联
在线程句柄上调用detach() 和 join()要小心
case1:不要在没有关联执行线程的std::thread对象上调用join() 或 detach()
std::thread threadObj(WorkerThread()); threadObj.join(); threadObj.join();// It will cause Program to Terminate
当join()函数在线程对象上执行,当join()返回时,std::thread 对象与他没有关联线程,如果在这样的对象上再次调用join()函数,那么它将导致程序终止。
类似的,调用detach()使std::thread对象没有链接任何线程函数,在这种情况下,在一个std::thread对象上调用detach()函数两次将导致程序终止。
std::thread threadObj(WorkerThread); threadObj.detach(); threadObj.detach();// It will cause Program to Terminate
因此,在每次调用join()或detach()前,需要检查线程是否join-able
std::thread threadObj(WorkerThread()) if (threadObj.joinable()) { std::cout << "Detaching Thread" << std::endl; threadObj.detach(); } if (threadObj.joinable()) { std::cout << "Detaching Thread" << std::endl; threadObj.detach(); } std::thread threadObj2(WorkerThread()) if (threadObj2.joinable()) { std::cout << "Joining Thread" << std::endl; threadObj2.join(); } if (threadObj2.joinable()) { std::cout << "Joining Thread" << std::endl; threadObj2.join(); }
case2:不要忘记使用关联的执行线程在std::thread对象上调用join或detach
如果std::thread关联的执行线程没有调用join和detach,那么在对象的析构期,它将终止程序
因为在析构期,它将检查线程是否仍然Join-able,然后终止程序
#include <iostream> #include <thread> #include <algorithm> class WorkerThread { public: void operator()() { std::cout << "Worker Thread" << std::endl; } }; int main() { std::thread threadObj((WorkerThread())); //如果没有在std::thread对象上调用join或detach,其析构函数将会终止程序 return 0; }
类似的,不能忘记在异常情况下调用join或detach
joinable()函数是一个布尔类型的函数,他会返回一个布尔值来表示当前的线程是否有可执行线程(能被join或者detach),因为相同的线程不能join两次,也不能join完再detach,同理也不能detach,所以joinable函数就是用来判断当前这个线程是否有可以joinable的。通常不能被joinable有以下几种情况:
1)由thread的缺省构造函数而造成的(thread()没有参数)。
2)该thread被move过(包括move构造和move赋值)。
3)该线程被join或者detach过。