c++11 Concurrency Guide------std::thread detailed

Source: Internet
Author: User
Tags thread class traits

Reference: https://github.com/forhappy/Cplusplus-Concurrency-In-Practice/blob/master/zh/chapter3-Thread/ Introduction-to-thread.md#stdthread-%e8%af%a6%e8%a7%a3

This section describes std::thread the usage in detail.

std::threadis <thread> declared in the header file, so the use std::thread needs to include the <thread> header file.

<thread>Header File Summary

<thread>The header file declares the Std::thread thread class and std::swap (Swaps two thread objects) auxiliary functions. In addition std::this_thread , the namespace is declared in the <thread> header file. The following is a summary of the header files defined by the C++11 standard <thread> :

See draft n3242=11-0012 section 30.3, Threads (p1133).

namespace std {    #define __STDCPP_THREADS__ __cplusplus    class thread;    void swap(thread& x, thread& y);    namespace this_thread {        thread::id get_id();        void yield();        template <class Clock, class Duration>        void sleep_until(const chrono::time_point<Clock, Duration>& abs_time);        template <class Rep, class Period>        void sleep_for(const chrono::duration<Rep, Period>& rel_time);    }        }

<thread>The header file mainly declares the std::thread class, in addition to the std::this_thread namespace declaration get_id , yield as well as the sleep_until sleep_for auxiliary functions, this chapter will be a little more detailed description std::thread of the class and related functions.

std::threadClass Summary

std::threadRepresents a thread object, the C++11 standard declares as follows:

  namespace std {class Thread {public://type declaration: Class ID;            typedef implementation-defined NATIVE_HANDLE_TYPE;            constructors, copy constructors, and destructor declarations: thread () noexcept; Template <class F, class ...            args> Explicit Thread (f&& F, Args&& .... Args);            ~thread ();            Thread (const thread&) = delete;            Thread (thread&&) noexcept;            thread& operator= (const thread&) = delete;            thread& operator= (thread&&) noexcept;            member function declaration: void swap (thread&) noexcept;            BOOL Joinable () const noexcept;            void join ();            void Detach ();            ID get_id () const noexcept;            Native_handle_type Native_handle ();    Static member function declaration: Static unsigned hardware_concurrency () noexcept; };}

std::threadThe main declaration of three kinds of functions: (1). constructors, copy constructors, and destructors; (2). member function; (3). static member functions. Also, the std::thread::id thread ID is represented, and the c++11 is declared as follows:

namespace std {    class thread::id {        public:            id() noexcept;    };    bool operator==(thread::id x, thread::id y) noexcept;    bool operator!=(thread::id x, thread::id y) noexcept;    bool operator<(thread::id x, thread::id y) noexcept;    bool operator<=(thread::id x, thread::id y) noexcept;    bool operator>(thread::id x, thread::id y) noexcept;    bool operator>=(thread::id x, thread::id y) noexcept;    template<class charT, class traits>    basic_ostream<charT, traits>&        operator<< (basic_ostream<charT, traits>& out, thread::id id);    // Hash 支持    template <class T> struct hash;    template <> struct hash<thread::id>;}
std::threadDetailed std::threadConstruct and assign values std::threadconstructor function
Default constructor (1) Thread () noexcept;
Initializing Constructors (2) Template <class Fn, class ... Args>
Explicit thread (fn&& Fn, Args&& .... Args);
copy constructor [deleted] (3) Thread (const thread&) = delete;
Move Constructor (4) Thread (thread&& x) noexcept;
    1. The default constructor (1) Creates an empty std::thread execution object.
    2. Initializes the constructor (2), creates an std::thread object that can be std::thread , the joinable newly generated thread invokes the fn function, and the function's arguments are given by args .
    3. The copy Constructor (disabled) (3) means that the std::thread object is non-copy constructed.
    4. The move constructor (4), the move constructor (move semantics is the new concept of c++11, as described in the appendix), x does not represent any execution object after the call succeeds std::thread .

Note: Objects that can be used joinable std::thread must be either the main thread join or set to before they are destroyed detached .

Std::thread examples of various constructors are as follows (reference):

#include <iostream>#include <utility>#include <thread>#include <chrono>#include <functional>#include <atomic>void f1(int n){    for (int i = 0; i < 5; ++i) {        std::cout << "Thread " << n << " executing\n";        std::this_thread::sleep_for(std::chrono::milliseconds(10));    }}void f2(int& n){    for (int i = 0; i < 5; ++i) {        std::cout << "Thread 2 executing\n";        ++n;        std::this_thread::sleep_for(std::chrono::milliseconds(10));    }}int main(){    int n = 0;    std::thread t1; // t1 is not a thread    std::thread t2(f1, n + 1); // pass by value    std::thread t3(f2, std::ref(n)); // pass by reference    std::thread t4(std::move(t3)); // t4 is now running f2(). t3 is no longer a thread    t2.join();    t4.join();    std::cout << "Final value of n is " << n << ‘\n‘;}
std::threadAssignment operation
Move Assignment Action (1) thread& operator= (thread&& rhs) noexcept;
Copy assignment operation [deleted] (2) thread& operator= (const thread&) = delete;
    1. The Move Assignment Action (1), if the current object is not available joinable , needs to pass an rvalue reference ( rhs ) to the move assignment operation, or joinable () An error if the current object is available terminate .
    2. The Copy assignment operation (2) is disabled, so the std::thread object cannot be copied and assigned to the value.

Take a look at the following example:

#include <stdio.h>#include <stdlib.h>#include <chrono>    // std::chrono::seconds#include <iostream>  // std::cout#include <thread>    // std::thread, std::this_thread::sleep_forvoid thread_task(int n) {    std::this_thread::sleep_for(std::chrono::seconds(n));    std::cout << "hello thread "        << std::this_thread::get_id()        << " paused " << n << " seconds" << std::endl;}int main(int argc, const char *argv[]){    std::thread threads[5];    std::cout << "Spawning 5 threads...\n";    for (int i = 0; i < 5; i++) {        threads[i] = std::thread(thread_task, i + 1);    }    std::cout << "Done spawning threads! Now wait for them to join\n";    for (auto& t: threads) {        t.join();    }    std::cout << "All threads joined.\n";    return EXIT_SUCCESS;}
Other member functions

The example in this section comes from http://en.cppreference.com

  • get_id : Gets the thread ID that returns an object of type   std::thread::id  . Take a look at the following example:

      #include <iostream> #include <thread> #include <chrono>void foo () {Std::this_ Thread::sleep_for (Std::chrono::seconds (1));}    int main () {std::thread T1 (foo);    Std::thread::id t1_id = t1.get_id ();    Std::thread T2 (foo);    Std::thread::id t2_id = t2.get_id ();    Std::cout << "T1 ' s ID:" << t1_id << ' \ n ';    Std::cout << "T2 ' s ID:" << t2_id << ' \ n ';    T1.join (); T2.join ();}  
  • joinable : Checks whether a thread can be join. Checks whether the current thread object represents an active execution thread, and the thread created by the default constructor cannot be join. In addition, if a thread has finished the task but is not being join, the thread will still be considered an active thread of execution and therefore can be join.

      #include <iostream> #include <thread> #include <chrono>void foo () {std::this_thread: : Sleep_for (Std::chrono::seconds (1));}    int main () {Std::thread T;    Std::cout << "Before starting, joinable:" << t.joinable () << ' \ n ';    t = Std::thread (foo);    Std::cout << "After starting, joinable:" << t.joinable () << ' \ n '; T.join ();}  
  • join: The join thread, which calls the function to block the current thread until the *this indicated thread has finished executing the join before returning.

    #include <iostream>#include <thread>#include <chrono>void foo(){    // simulate expensive operation    std::this_thread::sleep_for(std::chrono::seconds(1));}void bar(){    // simulate expensive operation    std::this_thread::sleep_for(std::chrono::seconds(1));}int main(){    std::cout << "starting first helper...\n";    std::thread helper1(foo);    std::cout << "starting second helper...\n";    std::thread helper2(bar);    std::cout << "waiting for helpers to finish..." << std::endl;    helper1.join();    helper2.join();    std::cout << "done!\n";}
  • detach: Detach thread. Separates the execution instance represented by the current thread object from the thread object, allowing the execution of the thread to be performed independently. Once the thread has finished executing, the resources it allocates will be freed.

After calling the Detach function:

    1. *thisInstances are no longer executed on behalf of any thread.
    2. joinable () = = False
    3. get_id () = = Std::thread::id ()

In addition, if there is an error or joinable() == false , it will be thrown std::system_error .

    #include <iostream>    #include <chrono>    #include <thread>    void independentThread()     {        std::cout << "Starting concurrent thread.\n";        std::this_thread::sleep_for(std::chrono::seconds(2));        std::cout << "Exiting concurrent thread.\n";    }    void threadCaller()     {        std::cout << "Starting thread caller.\n";        std::thread t(independentThread);        t.detach();        std::this_thread::sleep_for(std::chrono::seconds(1));        std::cout << "Exiting thread caller.\n";    }    int main()     {        threadCaller();        std::this_thread::sleep_for(std::chrono::seconds(5));    }
  • swap : Swap thread, swapping the underlying handle represented by two thread objects (underlying handles).

    #include <iostream>#include <thread>#include <chrono>void foo(){    std::this_thread::sleep_for(std::chrono::seconds(1));}void bar(){    std::this_thread::sleep_for(std::chrono::seconds(1));}int main(){    std::thread t1(foo);    std::thread t2(bar);    std::cout << "thread 1 id: " << t1.get_id() << std::endl;    std::cout << "thread 2 id: " << t2.get_id() << std::endl;    std::swap(t1, t2);    std::cout << "after std::swap(t1, t2):" << std::endl;    std::cout << "thread 1 id: " << t1.get_id() << std::endl;    std::cout << "thread 2 id: " << t2.get_id() << std::endl;    t1.swap(t2);    std::cout << "after t1.swap(t2):" << std::endl;    std::cout << "thread 1 id: " << t1.get_id() << std::endl;    std::cout << "thread 2 id: " << t2.get_id() << std::endl;    t1.join();    t2.join();}

The results of the implementation are as follows:

thread 1 id: 1892thread 2 id: 2584after std::swap(t1, t2):thread 1 id: 2584thread 2 id: 1892after t1.swap(t2):thread 1 id: 1892thread 2 id: 2584
  • native_handle: Returns native handle (because std::thread the implementation is related to the operating system, the function returns the thread handle associated with the std::thread implementation, for example, under the Posix-compliant platform (such as Unix/linux) is the Pthread library).

    #include <thread>#include <iostream>#include <chrono>#include <cstring>#include <pthread.h>std::mutex iomutex;void f(int num){    std::this_thread::sleep_for(std::chrono::seconds(1));   sched_param sch;   int policy;    pthread_getschedparam(pthread_self(), &policy, &sch);   std::lock_guard<std::mutex> lk(iomutex);   std::cout << "Thread " << num << " is executing at priority "             << sch.sched_priority << ‘\n‘;}int main(){    std::thread t1(f, 1), t2(f, 2);    sched_param sch;    int policy;     pthread_getschedparam(t1.native_handle(), &policy, &sch);    sch.sched_priority = 20;    if(pthread_setschedparam(t1.native_handle(), SCHED_FIFO, &sch)) {        std::cout << "Failed to setschedparam: " << std::strerror(errno) << ‘\n‘;    }    t1.join();    t2.join();}

The results of the implementation are as follows:

Thread 2 is executing at priority 0Thread 1 is executing at priority 20
    • hardware_concurrency[Static]: detects hardware concurrency and returns the number of thread concurrency supported by the current platform's thread implementation, but the return value is only used as a system hint (hint).

      #include <iostream>#include <thread>int main() {    unsigned int n = std::thread::hardware_concurrency();    std::cout << n << " concurrent threads are supported.\n";}
std::this_threadIntroduction to related helper functions in namespaces
  • get_id: Gets the thread ID.

      #include <iostream> #include <thread> #include <chrono> #include <mutex>std::    Mutex g_display_mutex;void foo () {Std::thread::id this_id = std::this_thread::get_id ();    G_display_mutex.lock ();    Std::cout << "Thread" << this_id << "sleeping...\n";    G_display_mutex.unlock (); Std::this_thread::sleep_for (Std::chrono::seconds (1));}    int main () {std::thread T1 (foo);    Std::thread T2 (foo);    T1.join (); T2.join ();}  
  • Yield: The current thread discards execution, and the operating system dispatches another thread to continue execution.

      #include <iostream> #include <chrono> #include <thread>//"Busy sleep" while Suggesting that and threads run//For a small amount of timevoid little_sleep (std::chrono::microseconds us) {Auto St    Art = Std::chrono::high_resolution_clock::now ();    Auto End = start + us;    do {Std::this_thread::yield (); } while (Std::chrono::high_resolution_clock::now () < end);}    int main () {Auto start = Std::chrono::high_resolution_clock::now ();    Little_sleep (std::chrono::microseconds (100));    Auto elapsed = Std::chrono::high_resolution_clock::now ()-Start; Std::cout << "waited for" << Std::chrono::d uration_cast<std::chrono::microseconds> (elapsed ). Count () << "microseconds\n";}  
  • Sleep_until: The thread sleeps to a specified moment (time point) before it wakes up again.

    template< class Clock, class Duration >void sleep_until( const std::chrono::time_point<Clock,Duration>& sleep_time );
  • Sleep_for: The thread sleeps on a specified time span, and the thread is woken up, but the actual sleep time may be longer than the time slice represented, for reasons such as thread scheduling sleep_duration .

    template< class Rep, class Period >void sleep_for( const std::chrono::duration<Rep,Period>& sleep_duration );#include <iostream>#include <chrono>#include <thread>int main(){    std::cout << "Hello waiter" << std::endl;    std::chrono::milliseconds dura( 2000 );    std::this_thread::sleep_for( dura );    std::cout << "Waited 2000 ms\n";}

The results of the implementation are as follows:

Hello waiterWaited 2000 ms

c++11 Concurrency Guide------std::thread detailed

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.