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

因此我们看到情况与 无关raise。因为您的begin/rescue周围有一个块,所以您只需比其他情况提前 5 秒raise退出线程。x

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

于 2011-09-30T18:15:46.597 回答