Недавно я работал с потоками 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
Почему потоку y разрешено запускаться, даже если m.unlock в потоке x никогда не выполняется?