Ruby 1.9.2 リファレンスマニュアル > ライブラリ一覧 > threadライブラリ > ConditionVariableクラス

class ConditionVariable

クラスの継承リスト: ConditionVariable < Object < Kernel < BasicObject

要約

スレッドの同期機構の一つである状態変数を実現するクラスです。

以下も ConditionVariable を理解するのに参考になります。

http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_threads.html#UF

Condition Variable とは

あるスレッド A が排他領域で動いていたとします。スレッド A は現在空いていない リソースが必要になったので空くまで待つことにしたとします。これはうまくいきません。 なぜなら、スレッド A は排他領域で動いているわけですから、他のスレッドは動くことが できません。リソースを空けることもできません。スレッド A がリソースの空きを 待っていても、いつまでも空くことはありません。

以上のような状況を解決するのが Condition Variable です。

スレッド a で条件(リソースが空いているかなど)が満たされるまで wait メソッドで スレッドを止めます。他のスレッド b において条件が満たされたなら signal メソッドでスレッド a に対して条件が成立したことを通知します。これが典型^な 使用例です。

mutex = Mutex.new
cv = ConditionVariable.new

a = Thread.start {
    mutex.synchronize {
      ...
      while (条件が満たされない)
        cv.wait(mutex)
      end
      ...
    }
}

b = Thread.start {
    mutex.synchronize {
      # 上の条件を満たすための操作
      cv.signal
    }
}

以下は [ruby-list:14445] で紹介されている例です。@q が空になった場合、 あるいは満たんになった場合に Condition Variable を使って wait しています。

require 'thread'

class TinyQueue
  def initialize(max=2)
    @max = max
    @full = ConditionVariable.new
    @empty = ConditionVariable.new
    @mutex = Mutex.new
    @q = []
  end

  def count
    @q.size
  end

  def enq(v)
    @mutex.synchronize{
      @full.wait(@mutex) if count == @max
      @q.push v
      @empty.signal if count == 1
    }
  end

  def deq
    @mutex.synchronize{
      @empty.wait(@mutex) if count == 0
      v = @q.shift
      @full.signal if count == (@max - 1)
      v
    }
  end

  alias send enq
  alias recv deq
end

if __FILE__ == $0
  q = TinyQueue.new(1)
  foods = 'Apple Banana Strawberry Udon Rice Milk'.split
  l = []

  th = Thread.new {
    for obj in foods
      q.send(obj)
      print "sent ", obj, "\n"
    end
    q.send nil
  }

  l.push th

  th = Thread.new {
    while obj = q.recv
      print "recv ", obj, "\n"
    end
  }
  l.push th

  l.each do |t|
    t.join
  end
end

実行すると以下のように出力します。

$ ruby condvar.rb
sent Apple
recv Apple
sent Banana
recv Banana
sent Strawberry
recv Strawberry
sent Udon
recv Udon
sent Rice
recv Rice
sent Milk
recv Milk

特異メソッド

定義 説明
new

状態変数を生成して返します。

インスタンスメソッド

定義 説明
broadcast

状態変数を待っているスレッドをすべて再開します。再開された スレッドは ConditionVariable#wait で指定した mutex のロックを試みます。

signal

状態変数を待っているスレッドを1つ再開します。再開された スレッドは ConditionVariable#wait で指定した mutex のロックを試みます。

wait(mutex)

mutex のロックを解放し、カレントスレッドを停止します。 ConditionVariable#signalまたは、 ConditionVariable#broadcastで送られたシグナルを 受け取ると、mutexのロックを取得し、実行状態となります。

継承したメソッド

! != == === =~ __id__ __send__ _dump class clone dclone display enum_for eql? equal? extend freeze frozen? hash initialize initialize_copy inspect instance_eval instance_exec instance_of? instance_variable_defined? instance_variable_get instance_variable_set instance_variables is_a? marshal_dump marshal_load method method_missing methods must_be must_be_close_to must_be_empty must_be_instance_of must_be_kind_of must_be_nil must_be_same_as must_be_within_epsilon must_equal must_include must_match must_raise must_respond_to must_send must_throw nil? pretty_inspect pretty_print pretty_print_cycle pretty_print_inspect pretty_print_instance_variables private_methods protected_methods public_methods remove_instance_variable respond_to? respond_to_missing? singleton_class singleton_method_added singleton_method_removed singleton_method_undefined singleton_methods taint tainted? tap to_a to_ary to_hash to_int to_io to_proc to_regexp to_s to_str to_yaml to_yaml_properties to_yaml_style trust untaint untrust untrusted? wont_be wont_be_close_to wont_be_empty wont_be_instance_of wont_be_kind_of wont_be_nil wont_be_same_as wont_be_within_epsilon wont_equal wont_include wont_match wont_respond_to