4

双方向同期に単一の条件変数を使用することはできますか (つまり、同じ条件変数で異なる時間に 2 つの異なる条件が待機されます)? いつでも条件変数を待機するスレッドは 1 つだけであると確信しています。以下のコード例は、私が考えていることを示しています。

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

std::condition_variable condvar;
std::mutex mutex;
int i;

void even()
{
    while (i < 10000) {
        std::unique_lock<std::mutex> lock(mutex);
        if (i % 2 != 0) {
            condvar.notify_one();
            condvar.wait(lock, [&](){ return i % 2 == 0; });
        }
        i++;
        std::cout << i << std::endl;
    }
    condvar.notify_one();
}

void odd()
{
    while (i < 10001) {
        std::unique_lock<std::mutex> lock(mutex);
        if (i % 2 != 1) {
            condvar.notify_one();
            condvar.wait(lock, [&](){ return i % 2 == 1; });
        }
        i++;
        std::cout << i << std::endl;
    }
}

int main()
{
    i = 0;
    std::thread a(even);
    std::thread b(odd);
    a.join();
    b.join();
}
4

2 に答える 2

6

Yes, it's perfectly safe. However, I wouldn't get into the habit of calling notify_one when you actually want to notify all threads waiting for the condition, even if you "know" only one thread will be waiting.

于 2013-05-02T18:12:22.807 に答える
1

基本的に、条件変数を通知することは、実際には「探している条件が発生した可能性がある」ことを宣言するだけです。

1 つの条件変数を使用する双方向通信で懸念される唯一の点は、使用可能なデータがない場合にスレッドが通知によって起動される可能性があることです。条件変数の適切な使用は while ループで行われるため、最悪の場合、スレッドは利用可能なデータがないと見なされ、スリープ状態に戻ります。これは完全に安全なので、1 つの条件変数で双方向通信が可能です。

そうは言っても、不必要にスレッドをウェイクアップする利点はほとんどないため、通常は、データを保護する 1 つのミューテックス (つまり、データにアクセスするにはミューテックスを保持する必要があります) と、異なる条件を示す 2 つの異なる条件変数を用意することをお勧めします。これにより、処理するデータがないことを発見するためにスレッドをウェイクアップする回数が最小限に抑えられます (「偽の」通知と呼ばれます)。

于 2013-09-02T06:08:56.327 に答える