マルチスレッドにおける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
次の例では、生産者はまずバッファが満たされているかどうかを確認しなければなりません(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
; }