2016-04-07 18 views
2

私はC++ 11でマルチスレッドについて学んでいますが、この単純なテストを試みましたが、出力は私が期待したものではありません。std :: mutexがstd :: coutのために正しくロックされていない

私は出力があることが予想
#include <thread> 
#include <iostream> 
#include <mutex> 

int main() { 
    auto function = [](int x) { 
     std::mutex m; 
     m.try_lock(); 
     std::cout << "Hello" << x << std::endl; 
     m.unlock(); 
     return; 
    }; 
    std::thread t1(function , 1); 
    std::thread t2(function, 2); 
    std::thread t3(function, 3); 
    std::thread t4(function, 4);  

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

    std::cin.get(); 
    return 0; 
} 

Hello1 
Hello2 
Hello3 
Hello4 

(そうでないかもしれないという順ではなく、別の行の各ハローと数)

代わりに、私はこのようなものだ:

HelloHello21 
Hello3 
Hello4 

または

HelloHello2 
1 
Hello3 
Hello4 

正しくロックされていないミューテックス以外にどんなパズルがあるのか​​は、常にハロー1になってしまうということです。

EDIT:それは何の違いを行う場合VS2015で行われ(それはすべての標準だからいけない?)

+1

関数に呼び出されるたびにローカル変数のコピーが取得されることを知っていますよね?したがって、この場合、すべてのスレッドは独自の別個のミューテックスを持っています。当然のことながら、1つのミューテックスをロックしても他のものはロックされません。 – immibis

+0

は、この種のエラーを避けるために、ロックしているものと同じスコープにミューテックスを置くことをお勧めします。 –

答えて

3

すべてのスレッドが同じmutexオブジェクトにアクセスする必要があるため、staticを使用する必要があります。また、try_lock()(またはlock())は、unlock()になる前に例外がスローされた場合に問題を引き起こします。 std::lock_guard<>()はこれを行うもっと安全な方法であり、関数の戻りか例外を経由するかどうかにかかわらず、スコープから外れると解放されるので、お勧めします。

は、関数の次のリビジョンを試してみてください。

auto function = [](int x) { 
    static std::mutex m; 
    std::lock_guard<std::mutex> mylock(m); 
    std::cout << "Hello" << x << std::endl; 
    return; 
}; 

は、より多くのためにhttp://en.cppreference.com/w/cpp/thread/lock_guardを参照してください。また

、あなたが将来的にミューテックスタイプを変更するかもしれないと思う(あるいは単に空想になろうとしている)あなたが推測されたテンプレートの種類でミューテックスを設定することができた場合:別に何サムすでにから

std::lock_guard<decltype(m)> mylock(m); 
+0

大変感謝しました!私はまだミューテックスを使ってもうまくいかなかった理由を知りたいと思っています:) –

+1

@StephanosPhilippidesあなたは4つの別々のミューテックスを作った。ちょうど1つのミューテックスを使用するはずです –

2

try_lock()は必ずしもmutexをロックしません。ミューテックスをロックする可能性があります。可能であれば、mutexをロックしようとします。既にロックされている場合は、mutexがロック解除されるまで待つことはありませんが、これが起こったという指示が返されます。

実際、あなたのコードは、出力、どのような形、問題、またはフォームをも効果的に同期させるわけではありません。

本当にmutexをロックする場合は、try_lock()の代わりにlock()を使用してください。

EDIT:他の人が指摘しているように、あなたのコードはスレッドごとに個別のミューテックスを効果的に作成するので、そのミューテックスをstaticにする必要があります。