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