6

最近、私は Ruby のスレッドを扱っていて、少し予期しない動作を発見しました。クリティカル セクションでは、呼び出しraiseによってミューテックスが解放されます。ブロックを使用してメソッドのこれを期待できましたが、 とが別々に呼び出されsynchronizeたときにも発生するようlockです。unlock

たとえば、以下のコードは次のように出力します。

$ ruby testmutex.rb 
x sync
y sync

y…宇宙が熱で死ぬまでブロックされると思っていた場所。

m = Mutex.new


x = Thread.new() do
  begin
    m.lock
      puts "x sync"
      sleep 5
      raise "x err"
      sleep 5
    m.unlock 
  rescue 
  end
end


y = Thread.new() do
  sleep 0.5
  m.lock
    puts "y sync"
  m.unlock 
end


x.join
y.join

x スレッドの m.unlock が実行されないにもかかわらず、y スレッドの実行が許可されるのはなぜですか?

4

1 に答える 1

4

と を削除しraiseても、動作は同じであることに注意してください。そのため、スレッドがミューテックスをロックした後、スレッドが終了し、ミューテックスがロック解除される状況があります。unlockxx

m = Mutex.new
Thread.new{ m.lock; p m.locked? }.join
#=> true

p m.locked?
#=> false

したがって、状況は とは無関係であることがわかりますraisebegin/rescueの周りにブロックがあるため、そうでない場合よりも 5 秒早くスレッドraiseを終了するだけです。x

おそらく、インタープリターは、スレッドによってロックされたミューテックスを追跡し、スレッドが終了したときに自動的かつ意図的にロックを解除します。(ただし、ソースコード検査でこれを裏付けることはできません。これは、動作に基づく単なる推測です。)

于 2011-09-30T18:15:46.597 に答える