3

2種類のデータ更新に、2つのミューテックスに関連付けられた1つの条件変数を使用してもいいですか。

基本的に、スレッド1とスレッド2があります。Thread1 は 2 種類のデータ更新を待機できるため、それぞれに 1 つずつ、2 つのミューテックスを取得しました。(これらすべてのデータに対して 1 つのミューテックスを使用できることはわかっていますが、これはこの質問のポイントではありませんよね?) そして、data2 が既に利用可能である間に data1 を待機させたくないので、条件変数は 1 つしか取得しませんでした。 . また、thread2 は data1 と data2 の両方を提供します。問題は、thread2 では、thread1 が現在 data1 または data2 を待機しているか、まったく待機していないかがわからないことです。

擬似コードは次のようになります。

global data:
    cond_var
    mutex1
    data1
    mutex2
    data2

thread1:
    while true
        lock1.lock(mutex1)
        if data1 is not available
        cond_var.wait(lock1)
        if data1 is available
            process data1
        lock1.unlock()

        lock2.lock(mutex2)
        if data2 is not available
            cond_var.wait(lock2)
        if data2 is available
            process data2
        lock2.unlock()

thread2:
    func1:
        lock1.lock(mutex1)
        update data1
        cond_var.notify_all()
        lock1.unlock()

    func2:
        lock2.lock(mutex2)
        update data2
        cond_var.notify_all()
        lock2.unlock()

外部は func1 または func2 を呼び出してデータを更新します。func1 または func2 が呼び出されると、lock1 または lock2 にあるかどうかに関係なく、cond_var が通知されます。cond_var の待機は while で囲まれていないため、cond_var が lock1 で起こされたが data2 が使用可能な場合、thread1 は data2 の処理に進みます。

実際の実装はboost::threadを介しており、私のテストのプラットフォームはLinuxなので、boost::threadはpthreadを介して実装する必要があります。

条件変数について読んだほとんどすべてのチュートリアルとドキュメントでは、1 つのミューテックスのみに関連付けられています。したがって、上記のプログラムが使用しても問題ないのか、それとも根本的に欠陥があるのか​​知りたいです。

4

1 に答える 1

1

これで結構です。

Boost.ThreadはC++11スレッドライブラリを実装し(v1.50まではいくつかの違いがありましたが、現在は非常に近いです)、そのスレッドライブラリは概念的にPthreadモデルに近いですが、異なるAPIを使用しているため、これらを確認できます。答えのスペック。

C++11標準のルールは次のとおりです。

必要なもの: 呼び出し元のスレッドによってロックされており、他のスレッドがこのオブジェクトを待機していないか、lock.owns_lock()同時に 待機しているすべて の( 、、、または)スレッドによって提供される引数ごとに同じ値を返します。truelock.mutex()
condition_variable
lock.mutex()lockvia waitwait_forwait_until

あなたの場合、ミューテックスは正しくロックされており、condvarで待機しているスレッドは1つだけなので、条件が満たされます。

POSIXのルールは同等ですが、言い方が異なります。

同じ条件変数での同時pthread_cond_timedwait()または操作に複数のミューテックスを使用することの影響は定義されていません。pthread_cond_wait()つまり、スレッドが条件変数を待機すると、条件変数は一意のミューテックスにバインドされ、この(動的)バインドは待機が戻ったときに終了します。

繰り返しますが、同時待機操作はありません。

一般に、異なるミューテックスを同時に使用するのを待たない限り、異なるミューテックスでcondvarを使用しても問題ありません。。condvarを待機するときは、POSIXで説明されているように、mutexと述語(「条件」)に関連付けます。condvarとmutexは一緒に「バインド」され、condvarは一度に複数のmutexにバインドされてはなりません。 。その理由は、condvarが待機からウェイクアップするときに、関連付けられているミューテックスを再取得する必要があるためです。異なるスレッドが異なるミューテックスでそれを使用した場合、間違ったスレッドで間違ったミューテックスを再ロックし、混乱を引き起こす可能性があります。スレッドは、待機していたミューテックスを再ロックしたと思ってウェイクアップしますが、実際には別のミューテックスがロックされています。おそらく、参照がないため、ロックを解除できません。デッドロックおよび/または未定義の動作とライオンとトラとクマ、ああ、私の。

あなたの場合、同時待機はないので問題ありません。複数のスレッドが待機している場合は、特定の待機で両方のスレッドが同じミューテックスを使用するようにする必要があります...追加の同期が必要になるため、これは難しいため、使用する方が簡単です。 2つのcondvars。

于 2012-10-18T09:50:46.280 に答える