Threads[ConditionVariable][Wait] - ある条件が満たされるまで待機
使い方
Wait( condId, mutexId )
パラメータ
condId - 状態変数識別子 (整数)
mutexId - ミューテックス識別子 (整数)
|
説明
|
|
•
|
Wait コマンドは状態変数識別子 condId が呼び出されるまで待機します。Wait コマンドは、ミューテックス識別子 mutexId を使うことができます。現在のスレッドは mutexId を Threads[Mutex][Lock] コマンドによって得る必要があります。
|
•
|
Wait を呼び出すと、スレッドは待機し mutexId は自動的にロック解除をします。再びスレッドを動かすと、スレッドは待機から返る前に、 mutexId を再び取得します。
|
•
|
Signal および Broadcast コマンドはロックされている mutexId を必要としませんが、よく使われます。Signal または Broadcast を呼ぶ間ロックしている mutexId によって、同時に Wait に入るスレッドがないように保証します。
|
|
|
例
|
|
これは生産者 - 消費者 (Producer/Consume) パターンの例です。
生産者は物を生産します (ここでは大域テーブルのタブ内の整数で表します) 。消費者は物があればを消費し、結果をテーブルの最後に挿入します。
2 つの状態変数と 1 つのミューテックスを持ちます。1 つ目の状態変数 (cp) は生産者のスレッドとして使います。生産者スレッドは、仕事がいっぱいであれば生産者の状態変数は待機します。もう一つの状態変数 (cc) は消費者が使います。物がない場合、消費者スレッドは生産者が物を作るまで待機します。
ミューテックスは大域変数タブへのアクセスを制御するために使います。
>
|
Producer := proc( m, cp, cc, max, mindiff )
global tab, e;
local i,j,n;
Threads:-Mutex:-Lock( m );
j := 0;
tab[ "maxjob" ] := mindiff;
tab[ "curjob" ] := 1;
for j from 1 to mindiff
do
tab[ j ] := 2*j;
end do;
Threads:-ConditionVariable:-Signal( cp );
Threads:-Mutex:-Unlock( m );
n := false;
while ( e )
do
Threads:-Mutex:-Lock( m );
j := tab[ "maxjob" ];
if ( j - tab[ "curjob" ] > mindiff/2 ) then
n := true;
Threads:-ConditionVariable:-Wait( cp, m );
end if;
for i from j to tab[ "curjob" ] + mindiff
do
tab[ i ] := 2*i;
end do;
tab[ "maxjob" ] := tab[ "curjob" ] + mindiff;
if ( n ) then
Threads:-ConditionVariable:-Broadcast( cc );
n := false;
end if;
Threads:-Mutex:-Unlock( m );
end do;
end proc:
|
>
|
Consumer := proc( m, cp, cc, max )
global tab, e;
local n, i, j, num;
num := 0;
while ( num < max )
do
Threads:-Mutex:-Lock( m );
while ( tab[ "curjob" ] = tab[ "maxjob" ] )
do
Threads:-ConditionVariable:-Signal( cp );
Threads:-ConditionVariable:-Wait( cc, m );
end do;
n := tab[ "curjob" ];
j := tab[ n ];
tab[ "curjob" ] := n + 1;
Threads:-Mutex:-Unlock( m );
j := add( i, i=1..j );
num := num+1;
Threads:-Mutex:-Lock( m );
tab[ n ] := j;
Threads:-Mutex:-Unlock( m );
end do;
end proc:
|
>
|
tab := table( ):
m := Threads:-Mutex:-Create();
|
>
|
cc := Threads:-ConditionVariable:-Create();
|
>
|
cp := Threads:-ConditionVariable:-Create();
|
生産者スレッドをスタートします。生産者スレッドがスタートするまで cp は待機しています。
>
|
Threads:-Mutex:-Lock( m );
id1 := Threads:-Create( Producer( m, cp, cc, 31, 10 ) );
|
>
|
Threads:-ConditionVariable:-Wait( cp, m );
Threads:-Mutex:-Unlock( m );
|
消費者スレッドをスタートします。毎回 100 個の物を消費し、5 つのスレッドで行うので 500 個の物を消費します。
>
|
id2 := [ seq( Threads:-Create( Consumer( m, cp, cc, 100 ) ), i=1..5 ) ];
|
終わるまで消費者スレッドを待機します。
>
|
Threads:-Wait( op( id2 ) );
Threads:-Mutex:-Lock( m );
|
生産者スレッドを終了します。
>
|
e := false:
Threads:-ConditionVariable:-Signal( cp );
Threads:-Mutex:-Unlock( m );
Threads:-Wait( id1 );
|
仕事の数を調べます。
>
|
print( tab[ "curjob" ] );
|
仕事の結果を調べます。
>
|
print( add( i, i=1..2*233 ) );
|
|
|