2016-05-12 13 views
5

std::condition_variableが追加のstd::mutexをパラメータとして必要とする理由を本当に理解しているかどうかわかりませんか?自己によってロックしてはいけないのでしょうか?std :: condition_variableなぜstd :: mutexが必要なのですか

#include <iostream> 
#include <condition_variable> 
#include <thread> 
#include <chrono> 

std::condition_variable cv; 
std::mutex cv_m; 
int i = 0; 
bool done = false; 

void waits() 
{ 
    std::unique_lock<std::mutex> lk(cv_m); 
    std::cout << "Waiting... \n"; 
    cv.wait(lk, []{return i == 1;}); 
    std::cout << "...finished waiting. i == 1\n"; 
    done = true; 
} 

void signals() 
{ 
    std::this_thread::sleep_for(std::chrono::seconds(1)); 
    std::cout << "Notifying falsely...\n"; 
    cv.notify_one(); // waiting thread is notified with i == 0. 
        // cv.wait wakes up, checks i, and goes back to waiting 

    std::unique_lock<std::mutex> lk(cv_m); 
    i = 1; 
    while (!done) 
    { 
     std::cout << "Notifying true change...\n"; 
     lk.unlock(); 
     cv.notify_one(); // waiting thread is notified with i == 1, cv.wait returns 
     std::this_thread::sleep_for(std::chrono::seconds(1)); 
     lk.lock(); 
    } 
} 

int main() 
{ 
    std::thread t1(waits), t2(signals); 
    t1.join(); 
    t2.join(); 
} 

二例では、それらは最初のミューテックス(signalsメソッド)をアンロック。なぜ彼らはこれをやっているのですか?最初にロックしてから、通知後にロックを解除しないでください。

答えて

2

複数のスレッドで作業しているときに覚えておいてほしいのは、質問したときに結果が嘘かもしれないということです。つまり、答えはあなたに与えられてから変更されているかもしれません。信頼できる質問をする唯一の方法は、効果的にシングルスレッド化することです。ミューテックスを入力してください。

条件変数はトリガーが条件を確認できるように待機します。その状態を確認するには、質問をする必要があります。

待機する前にロックしないと、質問をして条件を取得する可能性があり、その条件が偽であると言われます。トリガーが発生し、条件が真となると、これは嘘になります。しかし、これを知らないのは、mutexが存在しないため、これを効果的にシングルスレッド化しているからです。

代わりに、すでに実行されているため、起動しないトリガの条件変数を待機します。このデッドロック。

+1

この説明に感謝します。しかし、なぜこれが 'std :: condition_variable'の実装に直接組み込まれていないのか尋ねてもいいでしょうか? – Pascal

+0

です。そのため、条件変数のwait関数はパラメータとしてロックを受け取ります。 –

4

mutexは述語、つまりあなたが待っているものを保護します。あなたが待っているのは、必然的にスレッド間で共有されるため、何とか保護する必要があります。

上記の例では、i == 1が述語です。ミューテックスはiを保護します。

一歩を踏み出し、条件変数が必要な理由について考えてみると役に立ちます。 1つのスレッドは、進行中の進行を妨げるいくつかの状態を検出し、他のスレッドがその状態を変更するのを待つ必要があります。この状態の検出は、状態を共有する必要があるため、mutexの下で行わなければなりません(そうでなければ、別のスレッドがその状態をどのように変更することができますか?)。

しかし、スレッドはmutexを解放してから待つことができません。ミューテックスがリリースされた後、スレッドが待つ前に状態が変わった場合はどうなりますか?したがって、アトミックな「ロック解除と待機」操作が必要です。それは特に条件変数が提供するものです。

ミューテックスがないと、何がロックされますか?

ロックを解放する前または解放した後に条件変数を通知するかどうかの選択は、両側に利点がある複雑なものです。

+1

いい説明! –

関連する問題