C++11 began to support multithreaded programming, related classes and functions encapsulated in the standard library header file <thread>, while C + + multithreaded programming is very important is that when the user creates a Std::thread object, associated with the callable object, You need to call join () or detach () before the thread object is destroyed. where the join () function is used to bind a thread to ensure that the thread executes before the function that created the thread object exits, and the detach () function represents a detached thread, that is, to have the thread run in the background, the ownership and control of the thread is given to the C + + runtime library. If no join () or detach () is called before the thread object is destroyed, the program is terminated (thread's destructor calls Std::terminate ()).
If the user wants to detach a thread, it is generally possible to call detach () immediately after the threads are started. However, if you need to wait for a thread, the time to call join () is important: If the thread has an exception after the start and before the call to join (), the call to join () is skipped. One way to ensure that threads are waiting in an unusual environment is to use the Try/catch statement block:
1#include <thread>2#include <stdexcept>3 4 usingStd::thread;5 usingStd::runtime_error;6 7 voidfunc ();8 9 voidTestthread () {Ten thread Thrd (func); One Try A { - //... - } the Catch(Runtime_error re) - { - Thrd.join (); - Throwre; + } - Thrd.join (); +}
It is clear, however, that using the Try/catch statement block is verbose and prone to confusing scopes. A better approach is to use resource acquisition, which is the method of initializing (Resource acquisition is initialization, RAII), and RAII is a management resource for C + + and avoids the leakage of idiomatic methods. The C + + standard guarantees that, in any case, the constructed object will eventually be destroyed, i.e. its destructor will eventually be called. To put it simply, RAII's approach is to use an object that acquires resources at the time of its construction, controls access to the resource at the object's lifetime, and finally frees up resources when the object is refactored.
The code for using RAII is as follows:
1#include <thread>2 3 usingStd::thread;4 5 voidfunc ();6 7 classThread_raii {8 Private:9Thread &thrd;Ten Public: One ExplicitThread_raii (Thread &p_thrd): Thrd (P_THRD) {} A~Thread_raii () - { - if(Thrd.joinable ()) the { - Thrd.join (); - } - } + Thread_raii (const THREAD_RAII &) = delete; - Thread_raii & operator= (const THREAD_RAII &) = delete; + }; A at voidTestthread () - { - thread Thrd (func); - Thread_raii TR (THRD); - //... -}
When the function Testthread () executes to the end, the local object is destroyed in reverse order, so the TR is destroyed first, so that the Thrd object is combined, even if an exception is thrown when one of the previous statements is executed.
The above code also has two points to note:
① destructors need to check if THRD is joinable () before calling join (), because join () can only be called once for a thread.
The copy constructor and copy-copy operators of the ②thread_raii class are deleted because the Thread object is not copied (but can be moved) as IStream, Ostream, and Unique_ptr.
The wait of C + + multithreading in abnormal environment