Ruby 2.2.0 リファレンスマニュアル > ライブラリ一覧 > 組み込みライブラリ > Thread::ConditionVariableクラス
クラス・モジュールの継承リスト: Thread::ConditionVariable
< Object
< Kernel
< BasicObject
aliases: ConditionVariable
スレッドの同期機構の一つである状態変数を実現するクラスです。
以下も ConditionVariable を理解するのに参考になります。
https://ruby-doc.com/docs/ProgrammingRuby/html/tut_threads.html#UF
あるスレッド A が排他領域で動いていたとします。スレッド A は現在空いていないリソースが必要になったので空くまで待つことにしたとします。これはうまくいきません。なぜなら、スレッド A は排他領域で動いているわけですから、他のスレッドは動くことができません。リソースを空けることもできません。スレッド A がリソースの空きを待っていても、いつまでも空くことはありません。
以上のような状況を解決するのが Condition Variable です。
スレッド a で条件(リソースが空いているかなど)が満たされるまで wait メソッドでスレッドを止めます。他のスレッド b において条件が満たされたなら signal メソッドでスレッド a に対して条件が成立したことを通知します。これが典型的な使用例です。
mutex = Thread::Mutex.new
cv = Thread::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 しています。
class TinyQueue
def initialize(max=2)
@max = max
@full = Thread::ConditionVariable.new
@empty = Thread::ConditionVariable.new
@mutex = Thread::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 -> Thread::ConditionVariable
|
状態変数を生成して返します。 |
|
| 定義 | 説明 | |
|---|---|---|
broadcast -> self
|
状態変数を待っているスレッドをすべて再開します。再開されたスレッドは Thread::ConditionVariable#wait で指定した mutex のロックを試みます。 |
|
signal -> self
|
状態変数を待っているスレッドを1つ再開します。再開されたスレッドは Thread::ConditionVariable#wait で指定した mutex のロックを試みます。 |
|
wait(mutex, timeout = nil) -> self
|
mutex のロックを解放し、カレントスレッドを停止します。 Thread::ConditionVariable#signalまたは、 Thread::ConditionVariable#broadcastで送られたシグナルを受け取ると、mutexのロックを取得し、実行状態となります。 |
|
!
!=
__id__
__send__
instance_eval
instance_exec
method_missing
singleton_method_added
singleton_method_removed
singleton_method_undefined
!~
<=>
==
===
=~
_dump
class
clone
define_singleton_method
display
dup
enum_for
eql?
equal?
extend
freeze
frozen?
hash
initialize
initialize_clone
initialize_copy
initialize_dup
inspect
instance_of?
instance_variable_defined?
instance_variable_get
instance_variable_set
instance_variables
is_a?
itself
marshal_dump
marshal_load
method
methods
nil?
object_id
pretty_inspect
pretty_print
pretty_print_cycle
pretty_print_inspect
pretty_print_instance_variables
private_methods
protected_methods
public_method
public_methods
public_send
remove_instance_variable
respond_to?
respond_to_missing?
send
singleton_class
singleton_method
singleton_methods
taint
tainted?
tap
then
to_a
to_ary
to_hash
to_int
to_io
to_proc
to_regexp
to_s
to_str
to_yaml
trust
untaint
untrust
untrusted?
.yaml_tag
::ARGF
::ARGV
::DATA
::ENV
::RUBY_COPYRIGHT
::RUBY_DESCRIPTION
::RUBY_ENGINE
::RUBY_ENGINE_VERSION
::RUBY_PATCHLEVEL
::RUBY_PLATFORM
::RUBY_RELEASE_DATE
::RUBY_REVISION
::RUBY_VERSION
::SCRIPT_LINES__
::STDERR
::STDIN
::STDOUT
::TOPLEVEL_BINDING