2

次の場所で条件変数の記事を読んでいます

http://software.intel.com/en-us/blogs/2010/10/01/condition-variable-support-in-intel-threading-building-blocks/

Here we have following code as example

#include "tbb/compat/condition_variable"  
using namespace std;
condition_variable my_condition;
tbb::mutex my_mtx;
bool present = false;

void producer() {
        unique_lock<tbb::mutex> ul( my_mtx );
        present = true;
        my_condition.notify_one();
}

void consumer() {
        while( !present ) {
            unique_lock<tbb::mutex> ul( my_mtx );
            my_condition.wait( ul );
        }
}

私の理解では、条件変数を使用してイベントを待機しています。次の質問があります

  1. 条件変数を使用しているのに、なぜここでミューテックスを使用しているのですか?
  2. whileループのconsumer()関数で、ミューテックスを取得して条件を待機しています。コンシューマーがすでにミューテックスを取得している場合、プロデューサー関数はどのようにミューテックスをロックでき、デッドロックではないことを通知できますか?
  3. unique_lockはscoped_lockとどのように異なりますか?

私の質問を明確にするためにあなたの助けをありがとう。

4

4 に答える 4

3

条件変数を使用しているのに、なぜここでミューテックスを使用しているのですか?

条件変数の基本は、正しく機能するためにロックを必要とします。
ロックされたスレッドのみが条件変数の状態を変更しようとする必要があります (つまり、条件変数関数の 1 つを呼び出すことによって (実際に作業しているオブジェクトを保護するためでもあります))。

while ループの consumer() 関数では、ミューテックスを取得して条件を待機しています。コンシューマが既に取得している場合、プロデューサー関数はどのようにしてミューテックスをロックできますか

条件変数で wait() を呼び出すと、スレッドがスリープ状態になり、ミューテックスが解放されます。スレッドが起動されると、関数 wait() がユーザー コードに戻る前に、ロックを再取得する必要があります。

デッドロックではないことをどのように通知できますか?

スレッドをスリープ状態にする前に wait() がロックを解放しているため、デッドロックは発生しません。

unique_lock は scoped_lock とどう違うのですか?

このコンテキストでは、なし。ただし、これらの特定の実装がある場合は、実装を指定してください。詳細について説明できます。

于 2011-08-01T06:21:16.300 に答える
1

それは(明確にするために)あるべきです:

void producer() {
        unique_lock<tbb::mutex> ul( my_mtx ); // protect present
        present = true;
        my_condition.notify_one();
}

void consumer() {
        unique_lock<tbb::mutex> ul( my_mtx );   // protect preset
        while( !present ) {
            my_condition.wait( ul );
        }
}

から: http://www.boost.org/doc/libs/1_46_0/doc/html/thread/synchronization.html#thread.synchronization.condvar_ref.condition_variable.wait これは非常に似ています。

ボイド待機 (boost::unique_lock& ロック)

前提条件: ロックが現在のスレッドによってロックされており、現在 *this で待機している他のスレッドがないか、現在待機しているすべてのスレッドで wait または timed_wait への呼び出しで提供されたロック オブジェクトで mutex() メンバー関数が実行されているon *this は、この呼び出しを待機するために lock->mutex() と同じ値を返します。

効果: lock.unlock() を原子的に呼び出し、現在のスレッドをブロックします。スレッドは、this->notify_one() または this->notify_all() への呼び出しによって、または誤って通知されると、ブロックを解除します。スレッドが (何らかの理由で) ブロック解除されると、wait の呼び出しが戻る前に lock.lock() を呼び出すことによってロックが再取得されます。関数が例外で終了した場合、lock.lock() を呼び出してロックを再取得することもできます。

事後条件: ロックは現在のスレッドによってロックされています。

于 2011-08-01T05:16:25.177 に答える
0

Mutex は相互排除のためのものです (プロデューサーとコンシューマーがロックせずにグローバル状態を変更しないようにするため)、条件変数は何らかの順序付けを課すためのものです。

于 2011-08-01T05:15:12.347 に答える
0
  1. ミューテックスは、条件変数を保護するために使用されます
  2. my_condition.wait() を呼び出すとミューテックスは自動的にロック解除され、my_condition.wait() が戻るとミューテックスがロック解除され、while(!present) で条件をテストできます。つまり、別のスレッドの方が高速であるために wait() がミューテックスをロックできない場合、そのスレッドはブロックされます。高速なスレッドが終了すると、この wait() はミューテックスをロックして戻りましたが、条件が false になる可能性があり、スレッドは再び待機します。したがって、最初の回答が述べたように、ミューテックスは条件変数を保護するために使用されます。
于 2011-08-01T05:15:53.770 に答える