Ste*_*tam 5 ruby multithreading mutex exception synchronize
最近,我一直在使用Ruby的线程,并且发现了一些意外的行为。在关键部分,调用raise会导致互斥体释放。我可以期望这种synchronize方法及其功能块,但似乎在lock和unlock分别调用时也会发生。
例如,以下代码输出:
$ ruby testmutex.rb
x sync
y sync
Run Code Online (Sandbox Code Playgroud)
...在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
Run Code Online (Sandbox Code Playgroud)
为什么即使从未执行过x线程中的m.unlock,也允许y线程运行?
请注意,如果您删除 和raise,则unlock行为x是相同的。因此,您会遇到这样的情况:x线程锁定互斥锁,然后线程结束,互斥锁被解锁。
m = Mutex.new
Thread.new{ m.lock; p m.locked? }.join
#=> true
p m.locked?
#=> false
Run Code Online (Sandbox Code Playgroud)
因此我们看到这种情况与 无关raise。因为您begin/rescue的 周围有一个块,所以您只需比其他情况提前 5 秒raise退出线程即可。x
据推测,解释器会跟踪线程锁定的任何互斥体,并在线程终止时自动有意地解锁它们。(但是,我无法通过源代码检查来支持这一点。这只是基于行为的猜测。)