4

条件変数を使用して、何かが発生したことを他のスレッドに知らせることができます。

mutex m;
condition_variable cv;

thread t1([&cv]{
    // processing
    ...
    cv.notify_one();
});
...
unique_lock<std::mutex> lck(m);
cv.wait(lck);

しかし、ご覧のとおり、スレッドの処理が終了し、通知を待つ前に通知が通過する機会があるため、永遠に待機します。

その場合、一般的な解決策はフラグを使用することです。

mutex m;
condition_variable cv;
bool done = false;

thread t1([&cv,&done]{
    // processing
    ...
    done = true; 
    cv.notify_one();
});
...
unique_lock<std::mutex> lck(m);
cv.wait(lck, [&done]{return done;});

を使用する一般的な方法はフラグを使用してcondition_variableいますか、それとも私の解釈が間違っていますか?

4

2 に答える 2

7

条件変数は常に何らかの条件に関連付ける必要があり、これをテストする必要があります。

    unique_lock<mutex> lck(m);
    while (!何か)
      cv.wait(lck);

ミューテックスが保持されている間に条件がチェックされるため、ミューテックスが条件に関連付けられたデータを保護する必要があることを意味するため、テストと待機の間でデータが変更されないことがわかります。

一部の条件変数の実装 (pthreads ベースの実装を含む) は、偽装して、つまり誰もシグナルを送っていないときに起動する可能性があるため、テストはwhile単なるものではありません。そのため、ループで条件をチェックし、真でない間は再度待機する必要があります。述語を取り、述語が true を返すまで待機することで、誤ったウェイクアップを自動的に処理ifする のオーバーロードがあります。たとえば、条件をチェックするラムダを使用するように変更された上記の例を次に示します。wait

    unique_lock<mutex> lck(m);
    cv.wait(lck, [&] {何かを返す; });

(単純なケースでは、明示的なwhileループの方が読みやすいと思います。)

使用中の条件変数は、条件変数、ミューテックス、および述語からなる 3 つのタプルと考えることができます。これらは、条件変数を待機するために一緒に使用されることによって概念的に結合されます。特定の条件変数オブジェクトに対するすべての同時待機は、同じミューテックスを使用する必要があり、通常は同じ述語 (または、同じミューテックスによって保護された同じデータに依存する関連述語) も待機します。

于 2012-06-07T01:07:54.960 に答える
0

通常、condition_variable変数は、1 つのスレッドが続行できないことを検出し、何らかの条件(英語の意味で) が満たされるまで待機することを決定するシナリオで使用されます。それcondition_variable自体は、スレッドが続行する必要があることを通知する主要なメカニズムではありませんが、スレッドが待機している場合は、状態が変更された可能性があり、今すぐ続行しても問題ない可能性があるため、再チェックする必要があります。

最も単純な例の 1 つはプロデューサー/コンシューマー キューで、コンシューマーには次のようなコードがあります。

void consume() {
   empty.wait( [&] { return !queue.empty(); } );
   // extract data from the queue and consume it here
}

つまり、スレッドはcondition_variable変数を待機しているだけでなく、オブジェクトの状態がスレッドが続行できる状態になるまで待機しています。同様に、通知 acondition_variableは別のスレッドに続行するように指示するのではなく、状態が変更された可能性があるため、条件が満たされるのを待っているスレッドに再テストするよう通知するだけです。

ユースケースに戻ると、スレッドが続行するために満たす必要がある条件が他のスレッドがdoneである場合、そのようなフラグを使用しても問題ありません。

于 2012-06-06T22:15:49.327 に答える