2016-10-30 6 views
3

私はいくつかのジョブをスレッドプールに投稿し、それが終了するのを待っています。時には私のワーカースレッドが凍っているように見えるので、私はここで何かを見逃してしまったのだろうかと思います。このスレッドプールの使用は安全ですか?

私のメインスレッドは、このような労働者を起動します。

numJobsPosted = 0; 
for(auto entry : list) 
{ 
    numJobsPosted++; 
    threadPool->post(std::bind(&Controller::workerFunc, this, entry)); 
} 

std::unique_lock<std::mutex> lock(m_workerLock); 
while(numJobsPosted > 0) 
{ 
    m_workerCondition.wait(lock); 
} 

は今私のworkerFuncは次のようになります。

void Controller::workerFunc(Entry entry) 
{ 
    // do some work with entry 

    // notify finished 
    numJobsPosted--; 
    if(numJobsPosted <= 0) 
    { 
     // does the look need to be around the numJobsPosted-- ? 
     std::unique_lock<std::mutex> locker(m_workerLock); 
     m_workerCondition.notify_one(); 
    } 
} 

は、上記のコードは安全ですか、私の周りのロックを配置する必要があります減分演算子?

答えて

2

これは、スレッドプールの内部ロジックまたは設定の詳細に依存します(たとえばジョブが実際に連続して実行されるようにスレッドが1つの場合)numJobsPostedintまたは同様の組み込みタイプであると仮定すると、スレッドセーフではありません。 workerFunc
この行:それは、同時に複数のジョブで実行されます場合

numJobsPosted--; 

は非常によく競合条件の対象となりうる。

また、あなたのスレッドプールのpost関数が正確に何を行うのかよく分かりませんが、すぐにスレッドにワーカー関数を送り、ワーカー関数の中にはすぐに戻ることができる場合は、

numJobsPosted++; 

workerFuncでこの行:あなたのメインスレッドのコードで

numJobsPosted--; 

は、それを安全にするには、インスタンスのために作ることができnumJobsPosted原子、例えば

void Controller::workerFunc(Entry entry) 
{ 
    // do some work with entry 

    // notify finished 
    { 
     std::unique_lock<std::mutex> locker(m_workerLock); 
     numJobsPosted--; 
     if(numJobsPosted <= 0) 
     { 
      m_workerCondition.notify_one(); 
     } 
    } 
} 

は最初のレースコンディションのケースを解決することではなく、第二:

#include <atomic> 
std::atomic_int numJobsPosted; 

は、このようなあなたのworkerFunc何かを作る:(C++ 11で)このようにそれを宣言します。

(また、私は本当に操作周りのロジックを理解し、あなたがnumJobsPosted上でやっているテストが、私はそれがあなたの質問のポイントの横にはないと思う)

+0

うんそうnumJobsPostedだった通常のint型、I原子になるように変更します。あなたが投稿したコードについては、numJobsPostedを減らす必要があります.1より大きい場合でも、私はオペレータの周りでロックを移動すると思います。ありがとう。 –

+0

わかりましたので、わかりやすくするためにコードを編集します –

関連する問題