組込ライブラリ(Thread::ConditionVariable)
スレッド同期するための状態変数。
成果物
情報源
Thread::ConditionVariable
スレッドの同期機構の一つである状態変数を実現するクラスです。
以下も ConditionVariable を理解するのに参考になります。
https://ruby-doc.com/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 signal wait
メソッド | 概要 |
---|---|
wait |
mutexのロックを解放しカレントスレッドを停止する |
broadcast |
ロックし状態変数を待っているスレッドをすべて再開する |
signal |
ロックし状態変数を待っているスレッドを1つ再開する |
new
cv = ConditionVariable.new
所感
なんか複雑。
対象環境
- Raspbierry pi 4 Model B
- Raspberry Pi OS buster 10.0 2020-08-20 ※
- bash 5.0.3(1)-release
- Ruby 3.0.2
$ uname -a Linux raspberrypi 5.10.52-v7l+ #1441 SMP Tue Aug 3 18:11:56 BST 2021 armv7l GNU/Linux