Как именно исключение разблокирует мьютекс? - PullRequest
0 голосов
/ 26 июня 2019

Этот простой тест в большинстве случаев выглядит как
(1) rescue break, m.locked?: false
но иногда я вижу
(1) rescue break, m.locked?: true

m = Mutex.new

6.times do

    Thread.new do
        begin
            m.synchronize do
                puts 't1 action'
                3.times do
                    puts '.'
                    sleep 0.5
                end
                raise 'Break'
            end
        rescue 
            puts "(1) rescue break, m.locked?: #{m.locked?}"
            m.synchronize do
                sleep 0.1
            end
            puts '(2) after m {sleep}'
            sleep 0.1
            puts 'rescue break 2'
        end
    end

    sleep 0.1
    t2 = Thread.new do
        puts 't2 waiting for mutex'
        m.synchronize do
            puts '(3) t2 action'
        end
    end

    t2.join
    sleep 0.2
    puts;puts;
end

Я ожидал, что внутри спасательного блока мьютекс будет всегда разблокирован.

Окружающая среда: Ruby v2.6.3.62 (2019-04-16) [x64-mingw32]

1 Ответ

1 голос
/ 26 июня 2019

Никто не обещал, что процессор остановит мир, ожидая ваших действий :) Тем не менее, между

raise 'Break'

и

puts "(1) rescue break, m.locked?: #{m.locked?}"

существует другой поток, который может получить время выполнения и, в свою очередь, заблокировать мьютекс .


Обратите также внимание, что

    raise 'Break'
  end
rescue 
  puts "(1) rescue break, m.locked?: #{m.locked?}"

фактически совпадает с

  end
  puts "(1) rescue break, m.locked?: #{m.locked?}"

В последнем фрагменте должно быть ясно, что m может быть заблокирован другим потоком или нет; у нас это только что выпустили, так что без обещаний.

...