スレッドの同期機構の一つである状態変数を実現するクラス。 ConditionVariable オブジェクトはスレッドが待ち合わせを行う条 件をオブジェクト化したものです。
mutex = Mutex.new cv = ConditionVariable.new Thread.start { mutex.synchronize { ... while (条件が満たされない) cv.wait(m) end ... } }
あるスレッドで上のように条件が満たされるまで wait メソッドで スレッドを止めて、他のスレッドで
Thread.start { mutex.synchronize { # 上の条件を満たすための操作 cv.signal } }
として、signal メソッドで wait を実行しているスレッドに対し て条件が成立したことを通知するのが典型的な使用例です。
以下は 「Pthread プログラミング」にあった ConditionVariable の例をRuby で書いてみた。なぜか最後にデッドロックする。 *5
require 'thread' count_lock = Mutex.new count_hit_threshold = ConditionVariable.new count = 0 COUNT_THRESHOLD = 10 inc_count = proc { loop { count_lock.synchronize { count += 1 p [Thread.current, count] if count >= COUNT_THRESHOLD count_hit_threshold.signal Thread.exit end } } } ths = [] ths << Thread.new(&inc_count) ths << Thread.new(&inc_count) ths << Thread.new { loop { count_lock.synchronize { if count > 0 count -= 1 end p [Thread.current, count] } } } ths << Thread.new { cond_lock.synchronize { while (count < COUNT_THRESHOLD) count_hit_threshold.wait(count_lock) p [Thread.current, count, 'wait'] end } } ths.each {|t| t.join }
ConditionVariable.new
状態変数を生成して返します。
broadcast
状態変数を待っているスレッドをすべて再開します。再開された スレッドは ConditionVariable#wait で指定した mutex のロックを試みます。
実行待ちしていたスレッドの配列を返します。
signal
状態変数を待っているスレッドを1つ再開します。再開された スレッドは ConditionVariable#wait で指定した mutex のロックを試みます。
状態を待っているスレッドがあった場合は、そのスレッドを返します。
そうでなければ nil
を返します。
wait(mutex)
mutex のロックを開放し、カレントスレッドを停止します。 ConditionVariable#signalまたは、 ConditionVariable#broadcastで送られたシグナルを 受け取ると、mutexのロックを取得し、実行状態となります。
self
を返します。
*1あらい 2001-10-07: まだ理解できない、理解できないから書けない。
ruby-list:6735[外部]
*2あらい 2002-01-03: 全体的に記述が怪しいのですが間違ってて
も表に出さないと突っ込まれもしないのでコメントをはずしました。
このページ全文信じないように
*3m は mutex か
*4ruby-list:14445[外部] に例があります
*5waitの後に、mutexの解放を行っていませんでした。修正しておきます