c++11マルチスレッド(1)threadまとめ

11512 ワード

本文は主にC++におけるマルチスレッド同時操作について(cplusplus)を参照して説明し,マルチスレッドで使用されるいくつかのファイル学習について以下のいくつかの面から学習した.本文中のコードコンパイル可能な実行バージョンは本人github(アドレス)にアップロードされた.
マルチスレッド
C++における同時マルチスレッドに関する部分は,主に,,,,,の5つの部分を含む.
  • :このヘッダは主に2つのクラスを宣言し、std::atomicとstd::atomic_flagはまた,Cスタイルの原子タイプとCと互換性のある原子操作の関数のセットを宣言した.
  • :ヘッダファイルは主にstd::threadクラスを宣言し、std::this_threadネーミングスペースもこのヘッダファイルにあります.
  • :ヘッダファイルは、std::mutexシリーズクラス、std::lock_を含む反発量(mutex)に関連するクラスを主に宣言します.guard, std::unique_lock、その他のタイプと関数.
  • :ヘッダファイルは、std::condition_を含む条件変数に関連するクラスを主に宣言します.variableとstd::condition_variable_any.
  • :このヘッダファイルは主にstd::promise,std::package_を宣言しています.taskの2つのProviderクラスとstd::futureとstd::shared_futureの2つのFutureクラスには、関連するタイプと関数もあります.std::async()関数はこのヘッダファイルに宣言されます.

  • 1、 thread
    このセクションではthreadヘッダファイルの内容を説明し、コードアドレスを練習します.ヘッダファイルで宣言:threadスレッドとネーミングスペースthis_thread; threadには次のものが含まれます.
    (一)、メンバータイプ
    id
    Thread id (public member type )
    native_handle_type
    Native handle type (public member type )
    std::thread::idはスレッド呼び出しget_idとthis_thread::get_idの戻り値;thread::idデフォルト構造関数の結果はnon-joinableの値です.通常、他のスレッドとthread::get_idの結果を比較します.std::thread::native_handle_typeローカルハンドルタイプ.ライブラリがサポートされている場合、このメンバータイプはクラススレッドにのみ存在します.threadクラスメンバー関数thread::native_handleの戻り値.定義:typedef /* implementation-defined */ native_handle_type;(二)、チャンバーfunctions
    (constructor)
    Construct thread (public member function )
    (destructor)
    Thread destructor (public member function )
    operator=
    Move-assign thread (public member function )
    get_id
    Get thread id (public member function )
    joinable
    Check if joinable (public member function )
    join
    Join thread (public member function )
    detach
    Detach thread (public member function )
    swap
    Swap threads (public member function )
    native_handle
    Get native handle (public member function )
    hardware_concurrency [static]
    Detect hardware concurrency (public static member function )
    例1:
    // thread example
    #include          // std::cout
    #include          // std::thread
    void foo()  { 
        std::cout << "foo is called" << std::endl;
    }
    void bar(int x) {
         std::cout << "bar is called" << std::endl;
    }
    
    int main()
    {
         std::thread first (foo);    // spawn new thread that calls foo()
         std::thread second (bar,0);  // spawn new thread that calls bar(0)                                                 
         std::cout << "main, foo and bar now execute concurrently...
    "; // synchronize threads: first.join(); // pauses until first finishes second.join(); // pauses until second finishes std::cout << "foo and bar completed.
    "; return 0; }
  • コンストラクタ
  • default (1)              thread() noexcept;   
    initialization (2)       template   
                               explicit thread (Fn&& fn, Args&&... args);
    copy [deleted] (3)     thread (const thread&) = delete;
    move (4)                 thread (thread&& x) noexcept;
    

    (1)デフォルトコンストラクション関数は、実行スレッドを表さないスレッドオブジェクトを構築します.(2)初期化されたコンストラクション関数テンプレート関数は、新しい結合可能なスレッドを表すスレッドオブジェクトを構築する.新しい実行スレッド呼び出しfnはargsをパラメータとして渡す(そのlvalueまたはrvalue参照の減衰コピーを使用する).このコンストラクションの完了は、fnコピーの同期呼び出しを開始します.(3)コピー構造はコピー構造を許可しない(4)移動構造スレッドはxスレッドを取得し,この操作は移動スレッドの実行に影響を及ぼさず,プロセッサのみを転送する.xを完了すると、スレッドは表示されません.例2:
      // constructing threads
      #include        // std::cout
      #include          // std::atomic
      #include          // std::thread
      #include          // std::vector
    
      std::atomic global_counter (0);
    
      void increase_global (int n) { for (int i=0; i& variable, int n) { for (int i=0;   i {
        C() : std::atomic(0) {}
        void increase_member (int n) { for (int i=0; i threads;
    
        std::cout << "increase global counter with 10 threads...
    "; for (int i=1; i<=10; ++i) threads.push_back(std::thread(increase_global,1000)); std::cout << "increase counter (foo) with 10 threads using reference...
    "; std::atomic foo(0); for (int i=1; i<=10; ++i) { threads.push_back(std::thread(increase_reference,std::ref(foo),1000)); } std::cout << "increase counter (bar) with 10 threads using member...
    "; C bar; for (int i=1; i<=10; ++i) { threads.push_back(std::thread(&C::increase_member,std::ref(bar),1000)) ; } std::cout << "synchronizing all threads...
    "; for (auto& th : threads) th.join(); std::cout << "global_counter: " << global_counter << '
    '; std::cout << "foo: " << foo << '
    '; std::cout << "bar: " << bar << '
    '; return 0; }
  • 構造関数(destructor)std::thread::~threadはスレッドオブジェクトを破壊した.破棄時にスレッドが結合可能である場合、呼び出しは終了します().
  • std::thread::operator=: move (1) thread& operator= (thread&& rhs) noexcept; copy [deleted] (2) thread& operator= (const thread&) = delete; threadはコピーを許可しない.オブジェクトが現在joinableでない場合、rhs(ある場合)で表される実行スレッドが得られます.joinableの場合、呼び出しは終了します().割り当て"="演算子は右の式で、コピーされたthreadオブジェクトはスレッドではありません.例3:
  •   // example for thread::operator=
      #include        // std::cout
      #include          // std::thread, std::this_thread::sleep_for
      #include          // std::chrono::seconds
     
      void pause_thread(int n) 
      {
        std::this_thread::sleep_for (std::chrono::seconds(n));
        std::cout << "pause of " << n << " seconds ended
    "; } int main() { std::thread threads[5]; // default-constructed threads std::cout << "Spawning 5 threads...
    "; for (int i=0; i<5; ++i) threads[i] = std::thread(pause_thread,i+1); // move-assign threads std::cout << "Done spawning threads. Now waiting for them to join:
    "; for (int i=0; i<5; ++i) threads[i].join(); std::cout << "All threads joined!
    "; return 0; }
  • std::thread::get_idスレッドオブジェクトがjoinableの場合、関数はスレッドを一意に識別する値を返します.スレッド・オブジェクトがjoinableでない場合、関数はメンバー・タイプ・スレッドのデフォルトの構築オブジェクト:idを返します.例4:
  •   // thread::get_id / this_thread::get_id
      #include        // std::cout
      #include          // std::thread, std::thread::id,   std::this_thread::get_id
      #include          // std::chrono::seconds
     
      std::thread::id main_thread_id = std::this_thread::get_id();
    
      void is_main_thread() {
        if ( main_thread_id == std::this_thread::get_id() )
          std::cout << "This is the main thread.
    "; else std::cout << "This is not the main thread.
    "; } int main() { is_main_thread(); std::thread th (is_main_thread); th.join(); }
  • std::thread::joinableはスレッドオブジェクトがjoinableであるかどうかを返します.スレッドオブジェクトが実行するスレッドを表す場合は、joinableです.この場合、スレッドオブジェクトは接続できません.
  • がデフォルトの構造であれば.
  • それが既に移動されている場合(または別のスレッドオブジェクトを構築したり、割り当てたりします).
  • メンバーが参加または分離された場合に呼び出されます.

  • 例5:
      // example for thread::joinable
      #include        // std::cout
      #include          // std::thread
     
      void mythread() 
      {
        // do stuff...
      }
     
      int main() 
      {
        std::thread foo;
        std::thread bar(mythread);
    
        std::cout << "Joinable after construction:
    " << std::boolalpha; std::cout << "foo: " << foo.joinable() << '
    '; std::cout << "bar: " << bar.joinable() << '
    '; if (foo.joinable()) foo.join(); if (bar.joinable()) bar.join(); std::cout << "Joinable after joining:
    " << std::boolalpha; std::cout << "foo: " << foo.joinable() << '
    '; std::cout << "bar: " << bar.joinable() << '
    '; return 0; }
  • std::thread::join join関数は、スレッドの実行が完了したときに返されます.この関数は、関数が返されるときにスレッド内のすべての操作の完了と同期します.joinがコンストラクション関数呼び出しによって返されるまでjoinを呼び出し、呼び出しのスレッドをブロックする.この関数を呼び出すと、スレッドオブジェクトが接続できなくなり、安全に破棄できます.例6:
  •   // example for thread::join
      #include        // std::cout
      #include          // std::thread, std::this_thread::sleep_for
      #include          // std::chrono::seconds
     
      void pause_thread(int n) 
      {
        std::this_thread::sleep_for (std::chrono::seconds(n));
        std::cout << "pause of " << n << " seconds ended
    "; } int main() { std::cout << "Spawning 3 threads...
    "; std::thread t1 (pause_thread,1); std::thread t2 (pause_thread,2); std::thread t3 (pause_thread,3); std::cout << "Done spawning threads. Now waiting for them to join:
    "; t1.join(); t2.join(); t3.join(); std::cout << "All threads joined!
    "; return 0; }
  • std::thread::detach detachは呼び出しスレッドオブジェクトが表すスレッドを分離し、互いに独立して実行できるようにする.この2つのスレッドはいずれの方法でもブロックまたは同期しません.1つの実行が終了すると、そのリソースが解放されることに注意してください.この関数を呼び出すと、スレッドオブジェクトが接続できなくなり、安全に破棄できます.例7:
  •   #include        // std::cout
      #include          // std::thread, std::this_thread::sleep_for
      #include          // std::chrono::seconds
     
      void pause_thread(int n) 
      {
        std::this_thread::sleep_for (std::chrono::seconds(n));
        std::cout << "pause of " << n << " seconds ended
    "; } int main() { std::cout << "Spawning and detaching 3 threads...
    "; std::thread (pause_thread,1).detach(); std::thread (pause_thread,2).detach(); std::thread (pause_thread,3).detach(); std::cout << "Done spawning threads.
    "; std::cout << "(the main thread will now pause for 5 seconds)
    "; // give the detached threads time to finish (but not guaranteed!): pause_thread(5); return 0; }
  • std::thread::swap void swap (thread& x) noexcept;//Xとオブジェクトの状態を交換します.
  • std::thread::native_handleはローカル処理関数を取得します.ライブラリがサポートされている場合、このメンバー関数はクラススレッドにのみ存在します.存在する場合、スレッドに関連付けられた実装固有の情報にアクセスするための値が返されます.
  • std::thread::hardware_concurrency static unsigned hardware_concurrency() noexcept;//関数は、ハードウェアの同時検出を定義し、ハードウェアスレッドコンテキストの数を返します.この値の解釈は具体的なシステムと実現を見ることであり,正確ではないかもしれないが,近似値にすぎない.これは、システムで使用可能なプロセッサまたはカーネルの実際の数に一致する必要はありません.1つのシステムは、各処理ユニットの複数のスレッドをサポートしたり、プログラムのリソースへのアクセスを制限したりすることができます.この値が計算されていないか、定義されていない場合は、関数は0を返します.
  • std::swap(thread)std::swapは前述したメンバー関数とは異なり、メンバー関数ではありません.関数定義:void swap(thread&x,thread&y)noexcept;スレッドオブジェクトxとyの状態を交換する.x.swap(y)が呼び出されるように.

  • 本文は主にthreadについて述べ,次編c++11マルチスレッド(2)mutexのまとめである.