マルチスレッドにおけるQWaitConditionの応用


QWaitConditionでは、スレッドが状況に応じて別のスレッドを起動できます.1つ以上のスレッドは、1つのQWaitConditionを待つのをブロックし、wakeOne()またはwakeAll()で条件を設定します.wakeOne()はランダムに1つ起動し、wakeAll()はすべて起動します.
次の例では、生産者はまずバッファが満たされているかどうかを確認しなければなりません(numUsedBytes=BufferSize)、そうであれば、スレッドが停止してbufferNotFull条件を待つ必要があります.そうでない場合は、バッファでデータを生成しnumUsedBytesを増やし、条件bufferNotEmptyをアクティブにします.mutexを使用してnumUsedBytesへのアクセスを保護します.また、QWaitCondition::wait()は、呼び出しスレッドによってロック状態に初期化されるべきmutexをパラメータとして受信する.スレッドがスリープ状態になる前にmutexはロック解除されます.一方,スレッドが起動するとmutexはロック状態にあり,ロック状態から待機状態への変換は原子操作であり,競合条件の発生を阻止する.プログラムが実行されると、生産者だけが作業できます.消費者はbufferNotEmpty条件を待ち、生産者がバッファに1バイト入れるとbufferNotEmpty条件が励起され、消費者スレッドが起動する.
C/C++ code

    
    
    
    
const int DataSize = 100000 ; const int BufferSize = 8192 ; char buffer[BufferSize]; QWaitCondition bufferNotEmpty; QWaitCondition bufferNotFull; QMutex mutex; int numUsedBytes = 0 ; class Producer : public QThread { public : void run(); }; void Producer::run() { qsrand(QTime( 0 , 0 , 0 ).secsTo(QTime::currentTime())); for ( int i = 0 ; i < DataSize; ++ i) { mutex. lock (); if (numUsedBytes == BufferSize) bufferNotFull.wait( & mutex); mutex.unlock(); buffer[i % BufferSize] = " ACGT " [( int )qrand() % 4 ]; mutex. lock (); ++ numUsedBytes; bufferNotEmpty.wakeAll(); mutex.unlock(); } } class Consumer : public QThread { public : void run(); }; void Consumer::run() { for ( int i = 0 ; i < DataSize; ++ i) { mutex. lock (); if (numUsedBytes == 0 ) bufferNotEmpty.wait( & mutex); mutex.unlock(); fprintf(stderr, " %c " , buffer[i % BufferSize]); mutex. lock (); -- numUsedBytes; bufferNotFull.wakeAll(); mutex.unlock(); } fprintf(stderr, "
" ); } int main( int argc, char * argv[]) { QCoreApplication app(argc, argv); Producer producer; Consumer consumer; producer.start(); consumer.start(); producer.wait(); consumer.wait(); return 0 ; }