Recently, I have been working with Ruby's threads, and have uncovered a slightly unexpected behaviour. In a critical section, calling raise
causes the mutex to release. I could expect this of the synchronize
method, with its block, but it also seems to happen when lock
and unlock
are called separately.
For example, the code below outputs:
$ ruby testmutex.rb
x sync
y sync
...where I'd expect y
to be blocked until the heat death of the universe.
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
Why is the y thread allowed to run even though the m.unlock in the x thread is never executed?