Hatena::Grouparaistudy

czk-htnの日記

2006-08-16

[] 11. スレッドとプロセス(2)

11.2 スレッドスケジューラの制御

Threadに渡すメソッドはThreadを明示的に指定してあげる。特にスレッドCは"Thread"をつけないとそのままexitしてしまう。

 = Thread.new { Thread.raise }
b = Thread.new { Thread.stop }
c = Thread.new { Thread.exit }

puts a.status
puts b.status
puts c.status
puts Thread.current.status
% ruby sample02.rb
nil
sleep
false
run

11.3 相互排他

  • Thread.critical=trueにするとスケジューラは既存のスレッドの実行をスケジューリングしなくなる
    • このメソッドはおそろしく不便です
    • 代替手段
  • Mutexクラス
    • JavaのSynchronizeの書き方に似ている
    • Mutex#synchronizeに渡したブロック内は一貫性が保証される
    • 処理速度はかな〜〜り低下する
  • ConditionVariable(条件変数

ちなみにセマフォっていうのは同期機構の一種。

下のサンプルでは本の例題に加え、スレッドCを追加してみた。まぁ当然デッドロックする。1つのM

utex,CVで制御できるのは1クリティカルセクションってことか。

require 'thread'
mutex = Mutex.new
cv = ConditionVariable.new

a = Thread.new {
    mutex.synchronize {
      puts "A: クリティカルセクション、CVを待ちます"
      cv.wait(mutex)
      puts "A: クリティカルセクションを再度獲得"
    }
}

b = Thread.new {
    mutex.synchronize {
      puts "B: クリティカルセクション、CVを利用します"
      cv.signal
      puts "B: まだクリティカルセクション内、CVを解放します"
    }
}

c = Thread.new {
    mutex.synchronize {
      puts "C: クリティカルセクション、CVを待ちます"
      cv.wait(mutex)
      puts "C: クリティカルセクションを再度獲得"
    }
}

a.join
b.join
c.join
% ruby sample03.rb
A: クリティカルセクション、CVを待ちます
B: クリティカルセクション、CVを利用します
B: まだクリティカルセクション内、CVを解放します
A: クリティカルセクションを再度獲得
C: クリティカルセクション、CVを待ちます
deadlock 0x34740: sleep:J(0x209d4) (main) - sample03.rb:31
deadlock 0x209d4: sleep:-  - /opt/local/lib/ruby/1.8/thread.rb:203
/opt/local/lib/ruby/1.8/thread.rb:203: Thread(0x209d4): deadlock (fatal)
トラックバック - http://araistudy.g.hatena.ne.jp/czk-htn/20060816