2017-10-13 4 views
2

私はmutexをスレッド間で同期するために使用したこのコードは、0から10までの3つの行をエレガントに印刷すると考えました。なぜmutexでスレッドから奇妙な印刷

#include <iostream> 
#include <mutex> 
#include <thread> 

using namespace std; 

struct A 
{ 
    void run() 
    {  
     lock_guard<mutex> l(mutex); 
     int i = 0; 
     while (i <= 10) 
      cout << "i = " << i++ << endl;    
    } 

    std::mutex mut; 
}; 

int main() 
{ 
    A a; 
    thread t1(&A::run, &a); 
    thread t2(&A::run, &a); 
    thread t3(&A::run, &a); 

    t1.join(); 
    t2.join(); 
    t3.join(); 
} 

何らかの理由で出力の開始が常に多少なりとも損なわれます。残りの部分は時には大丈夫、時にはそうではない。だから、明らかに、それは同期されていません。あるスレッドがmutexをロックすると、他のスレッドはrunメソッドの本体に入りません。しかし、明らかにそれは真実ではありません。

i = i = 00i = 0 

i = 1 
i = 2 
i = 3 

誰かがこれを説明できますか?

スレッドコンストラクタの 'a'オブジェクトをstd :: refで囲む必要があるかもしれないと思ったが、これは役に立たない。

+3

問題に直面したときには、「私が知っている、私はスレッドを使用します」と思う人もいれば、2人がerpoblesmsを持っています。 – Slava

+6

'lock_guard l(mutex);'と 'std :: mutex mut;'? –

+0

役に立たなくても、ロックの使用が魅力的ではないことがわかりました。ロックガードを持つ印刷メソッドを作成し、ループ内からprintメソッドを呼び出します。ロックは可能な限り最小限に抑える必要があります。印刷を守る必要があるときだけ、すべての「実行」メソッドをブロックすることはできません。 – Kieveli

答えて

7

この:

lock_guard<mutex> l(mutex); 

は、あなたが何を望むか、おそらくではありませんstd::mutexパラメータを受け入れるタイプlock_guard<mutex>の機能lを宣言します。ラップ条件std::lock_guardが正しく使用されていないため、競合状態が発生します。

std::lock_guard<std::mutex> l(mut); 

using namespace std;を使用していないこの混乱を避けるために:あなたはタイプstd::lock_guardの変数を宣言し、代わりにmutメンバ変数で初期化します。

+2

Most Vexing Parseの興味深いひねりです。 – Persixty

0

これはタイプミスで、 'Lock_guard l(mut);にする必要があります。それでも、これを試してみてください。

#include <iostream> 
#include <mutex> 
#include <thread> 

using namespace std; 

struct A 
{ 
    void run() 
    {  
     int i = 0; 
     while (i <= 10) 
      printOutput(i); 
    } 

    void printOutput(int i) 
    { 
     lock_guard<mutex> l(mut); 
     cout << "i = " << i++ << endl;    
    } 

    std::mutex mut; 
}; 

int main() 
{ 
    A a; 
    thread t1(&A::run, &a); 
    thread t2(&A::run, &a); 
    thread t3(&A::run, &a); 

    t1.join(); 
    t2.join(); 
    t3.join(); 
} 

私はあなたが時々...出力はもっと面白いと思います。デバッグコンパイルでそれを試して最適化してください - それらは異なった動作をするかもしれません。

1

答えは私がタイプミスをしたことです。 'mut'と書くのではなく、 'mutex'とタイプしました。コードは驚くほどコンパイルされましたが、コメントに記載されているように、私は関数を宣言し、mutexをロックしませんでした( '最も困惑します')。そのため、 'run'メソッドのコードはスレッド間で同期されませんでした。

コメントに記載されているように、 'using namespace std'を使用しないと、私はすぐにメンバー変数 'std :: mutex' '

関連する問題