2017-03-22 10 views
1
#include <iostream> 
#include <mutex> 
#include <condition_variable> 
#include <thread> 
using namespace std; 
int num = 1; 
#define NUM 20 
condition_variable odd; 
condition_variable even; 
mutex mut; 
void thread_odd() 
{ 
     while(num < NUM -1) 
     { 
      if(num%2 != 1) 
      { 
        unique_lock<mutex> lock(mut); 
        odd.wait(lock); 
      } 
      cout<<"ODD : "<<num<<endl; 
      num++; 
      even.notify_all(); // Line X 
     } 
} 
void thread_even() 
{ 
     while(num < NUM) 
     { 
      if(num%2 != 0) 
      { 
        unique_lock<mutex> lock(mut); 
        even.wait(lock); 
      } 
      cout<<"EVEN : "<<num<<endl; 
      num++; 
      odd.notify_all(); 
     } 
} 
int main() 
{ 
     thread t1(thread_odd), t2(thread_even); 
     t1.join(); 
     t2.join(); 
     return 0; 
} 

/*上記は、ODD & EVEN数値を同期して(1つずつ)印刷するプログラムです。ほとんどの場合、コードは大丈夫です。 しかし、時にはデッドロック状況に陥っています。 奇数のスレッドがnotify_allを打つと、偶数のスレッドが起動する前に、奇数のスレッドがロックを獲得した後、偶数のスレッドが起動していない間に待ち状態になります。 ディーロックの状況から離れる。 notify_allをnotify_oneに置き換えようとしましたが、 が問題は解決しません。デザインの変更は必要ですか? または、私が完全に欠けているものはありますか? */notifyallはC++マルチスレッドでは動作しません。デッドロックが発生する

+0

'thread_odd()'が 'even.notify_all()'を呼び出す前に、 'thread_even()'が 'even.wait()'を呼び出すようにする必要があります。 – mkcms

答えて

1

一般的な並行プログラムでは、共有リソースにアクセスしてそれを読んで変更する(あなたの場合はnumのモジュロ演算子が最初に読まれ、num ++が書いています)、そのリソースへの相互排他アクセスを取得し、はそのリソースを完了するまでを解放しません。

このルールに従わないように、if-statementスコープが存在する場合、ロックが解除されます。

次のようにあなたのコードを変更する場合は、デッドロックはありません。私は通知する前にロックを解除していますか

#include <iostream> 
#include <mutex> 
#include <condition_variable> 
#include <thread> 
using namespace std; 
int num = 1; 
#define NUM 20 
condition_variable odd; 
condition_variable even; 
mutex mut; 
void thread_odd() 
{ 
    while(num < NUM -1) 
    { 
     unique_lock<mutex> lock(mut); 
     if(num%2 != 1) 
     { 
      odd.wait(lock); 
     } 
     cout<<"ODD : "<<num<<endl; 
     num++; 
     lock.unlock(); 
     even.notify_all(); // Line X 
    } 
} 
void thread_even() 
{ 
    while(num < NUM) 
    { 
     unique_lock<mutex> lock(mut); 
     if(num%2 != 0) 
     { 
      even.wait(lock); 
     } 
     cout<<"EVEN : "<<num<<endl; 
     num++; 
     lock.unlock(); 
     odd.notify_all(); 
    } 
} 
int main() 
{ 
    thread t1(thread_odd), t2(thread_even); 
    t1.join(); 
    t2.join(); 
    return 0; 
} 

お知らせ。 C++では、これは(Javaとは対照的に)可能であるだけでなく、リリーサが批判的なブロックに貪欲に再入する可能性を減らすので推奨されます。あなたはこの最後のポイントhereにいくつかの洞察を得るでしょう。

+0

傑作。それを考えていたはずです。どうもありがとうございました 。 – user3798283

関連する問題