ruby异常如何导致mutices解锁?

最近,我一直在使用
Ruby的线程,并发现了一个略微出乎意料的行为.在关键部分,调用raise会导致互斥锁释放.我可以期待这个同步方法,它的块,但它似乎也发生在单独调用锁和解锁时.

例如,下面的代码输出:

$ruby testmutex.rb 
x sync
y sync

…我希望在宇宙热死之前阻止你.

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线程也可以运行?

最佳答案 请注意,如果从x中删除加注和解锁,则行为是相同的.所以你有一种情况,x线程锁定互斥锁,然后线程结束,互斥锁被解锁.

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

p m.locked?
#=> false

因此,我们看到情况与提高无关.因为你的加注周围有一个开始/救援块,你只需要提前5秒退出x线程.

据推测,解释器会保留由线程锁定的任何互斥锁的跟踪,并在线程死亡时自动并故意解锁它们. (但我无法通过源代码检查来支持这一点.这只是基于行为的猜测.)

点赞