2017-01-02 8 views
2

スレッドプールを作成して、4つのスレッド間で100回の計算を分散させました。スレッドプールスタック

4つの計算の後で次のコードがスタックする理由を理解できません。各計算の後、スレッドは解放されなければならず、私はプログラムが続行するように.joinable()がfalseを返すことを期待しています。

結果:

[[[01] calculated 
] calculated 
2] calculated 
[3] calculated 

コード:

#include <string> 
#include <iostream> 
#include <vector> 
#include <thread> 
#include <boost/date_time/posix_time/posix_time.hpp> 
#include <boost/thread/thread.hpp> 
#include <cmath> 

class AClass 
{ 
public: 

    void calculation_single(std::vector<double> *s,int index) 
    { 
     (*s)[index]=sin(double(index)); 
     std::cout<<"["<<index<<"] calculated \n"; 
    } 

    void calculation() 
    { 
     const uint N_nums=100; 
     const uint N_threads=4; 
     std::vector<double> A; 
     A.assign(N_nums,0.0); 
     std::vector<std::thread> thread_pool; 
     for(uint i=0;i<N_threads;i++) 
      thread_pool.push_back(std::thread()); 

     uint A_index=0; 
     while(A_index<N_nums) 
     { 
      int free_thread=-1; 
      for(uint i=0;i<N_threads && free_thread<0;i++) 
       if(!thread_pool[i].joinable()) 
        free_thread=i; 
      if(free_thread>-1) 
      { 
       thread_pool[free_thread]= 
        std::thread(
         &AClass::calculation_single, 
         this, 
         &A, 
         int(A_index)); 
       A_index++; 
      } 
      else 
      { 
       boost::this_thread::sleep(boost::posix_time::milliseconds(1)); 
      } 

     } 

     // wait for tasks to finish 
     for(std::thread& th : thread_pool) 
      th.join(); 
    } 

}; 

int main() 
{ 
    AClass obj; 
    obj.calculation(); 
    return 0; 
} 

答えて

2

スレッド、それは基本的に空でない場合に結合可能です。

タスクが完了したスレッドは空ではありません。

std::thread bob; 

bobは参加できません。

あなたのスレッドはあります。あなたがしているものは参加できません。

また、ビジー状態の待機スレッドは厄介なスレッドプールです。

タスクを消費するスレッドのプールとアボートメソッドを持つコンシューマプロデューサキューを作成します。パッケージタスクを使用してタスクをキューに送り、std::future<T>を返します。タスクごとに新しいスレッドを生成しないでください。

+0

このコードはどのように修正する必要がありますか? 'joinable'と置き換えるべきものは? – ar2015

+0

@ ar2015 - スレッド単位のmutexで保護されたフラグを設定し、条件変数を通知することによって、各スレッドがタスクを完了したことを示す必要があります。メインループは、すべてのスレッドが結合可能であると判断すると、ミューテックスを取得し、完了フラグの少なくとも1つが設定されるまで条件変数を待機し、その後、対応するスレッドに結合します。これはまた、愚かなビジー待機ポーリングを取り除くでしょう。 –

+0

なぜ*忙しい待っている*悪い考えですか? – ar2015