2009-06-23 5 views
1

このコードは、プロデューサのvoid push(data)内部のミューテックスを待つでしょうか?このようなブースト条件コードの使用に問題はありますか?

もしそうなら、どのように回避できますか?

boost::mutex access; 
boost::condition cond; 

// consumer 
data read() 
{ 
    boost::mutex::scoped_lock lock(access); 

    // this blocks until the data is ready 
    cond.wait(lock); 

    // queue is ready 
    return data_from_queue(); 
} 

// producer 
void push(data) 
{ 
    //<--- will a block ever happen here? 
    boost::mutex::scoped_lock lock(access); 
    // add data to queue 

    cond.notify_one(); 
} 

私は(;;)ループ用のスレッドプールを持っていて、このプール内のスレッドからread()を呼び出すとします。その後、私はそれに関するデータを処理します。私はいくつかの外部スレッドでpush()を呼び出します。私の質問は、その外部スレッドは、プッシュ(データ)の呼び出しでブロックすることができますか?

答えて

0

.wait()が呼び出されると、スレッドプール内の呼び出しスレッドがブロックされ、mutexが解放されます。誰かがnotify_one()またはnotify_all()を呼び出したときに戻ります。ブロックされたスレッドが返る前に、mutexを再度取得し、スレッドプール内のスレッドのブロックを解除します。

したがって、外部スレッドによるvoid push(data)の呼び出しは、.wait()が呼び出されるまで一時的にブロックされます。

boost documentation on the condition's wait functionを参照してください。

+2

これは当てはまりません。 void push(data)は、waitが呼び出されるまでブロックされません。ミューテックスを取得できない場合にのみブロックされ、他の誰かがミューテックスを解放するまで待たなければなりません。 データ読み取り()関数は、実際に待ち行列に項目があるかどうかをチェックしなければなりません(wait()を呼び出していない間に項目が追加されたか、または偽の起床が発生した可能性があります)。関数は "while(キューは空)cond.wait(ロック); return data_from_queue();" – nos

8

waitnotifyと呼ばれることなく返されます。これはspurious wakeupと呼ばれます。これを処理するには、条件を使用するコードは、期待される条件が実際に有効であることを確認するwaitの周りに常にループを持つ必要があります。例:

queue data_queue; 
boost::mutex access; 
boost::condition cond; 

// consumer 
data read() 
{ 
    boost::mutex::scoped_lock lock(access); 

    while (queue.is_empty()) { 
    // this blocks until the data is ready 
    cond.wait(lock); 
    } 

    // queue is ready 
    return data_from_queue(); 
} 

// producer 
void push(data) 
{ 
    boost::mutex::scoped_lock lock(access); 

    // add data to queue 
    queue.push_back(data); 

    cond.notify_one(); 
} 

概念的に、「条件」は誤解を招くようなものです。代わりに、それをシグナルと考えることができます。目を覚ますために別のスレッドを通知していますが、何かを約束しているわけではありません。ちょっと、ちょっと、準備が整っているデータがあるかもしれませんが、なぜチェックしてみませんか? "

+0

私は(;;)ループ用のスレッドプールを持っていて、このプール内のスレッドからread()を呼び出しているとします。その後、私はそれに関するデータを処理します。私はいくつかの外部スレッドでpush()を呼び出します。私の質問は、その外部スレッドは、プッシュ(データ)の呼び出しでブロックすることができますか? –

+0

たとえば、キュ​​ーが空であるとします( –

+0

)read()から返されるまでアクセスmutexは保持されませんか? –

関連する問題