web-dev-qa-db-ja.com

生産者/消費者の状況での条件変数の使用

条件変数と、それを生産者/消費者の状況で使用する方法について学習しようとしています。あるスレッドが番号をキューにプッシュし、別のスレッドがキューから番号をポップするキューがあります。生成スレッドによって配置されたデータがある場合に、条件変数を使用して消費スレッドに信号を送りたいと思います。問題は、最大2つのアイテムをキューにプッシュしてからハングする場合があります(またはほとんどの場合)。デバッグモードで実行すると停止する場所をproduce()関数で示しました。なぜこれが起こっているのかを誰かが指摘するのを手伝ってもらえますか?

次のグローバル変数があります。


boost::mutex mutexQ;               // mutex protecting the queue
boost::mutex mutexCond;            // mutex for the condition variable
boost::condition_variable condQ;

以下は私の消費者スレッドです:


void consume()
{
    while( !bStop )   // globally declared, stops when ESC key is pressed
    {
        boost::unique_lock lock( mutexCond );
        while( !bDataReady )
        {
            condQ.wait( lock );
        }

        // Process data
        if( !messageQ.empty() )
        {
            boost::mutex::scoped_lock lock( mutexQ );

            string s = messageQ.front();   
            messageQ.pop();
        }
    }
}

以下は私のプロデューサースレッドです:


void produce()
{
    int i = 0;

    while(( !bStop ) && ( i < MESSAGE ))    // MESSAGE currently set to 10
    {
        stringstream out;
        out << i;
        string s = out.str();

        boost::mutex::scoped_lock lock( mutexQ );
        messageQ.Push( s );

        i++;
        {
            boost::lock_guard lock( mutexCond );  // HANGS here
            bDataReady = true;
        }
        condQ.notify_one();
    }
}
26
jasonline

条件変数で使用するのと同じミューテックスを使用してキューを保護する必要があります。

必要なのはこれだけです。

void consume()
{
    while( !bStop )
    {
        boost::scoped_lock lock( mutexQ);
        // Process data
        while( messageQ.empty() ) // while - to guard agains spurious wakeups
        {
            condQ.wait( lock );

        }
        string s = messageQ.front();            
        messageQ.pop();
    }
}

void produce()
{
    int i = 0;

    while(( !bStop ) && ( i < MESSAGE ))
    {
        stringstream out;
        out << i;
        string s = out.str();

        boost::mutex::scoped_lock lock( mutexQ );
        messageQ.Push( s );
        i++;
        condQ.notify_one();
    }
}
36
nos