почему поток не ожидает блокировки объекта в ответ на прерывание?

почему поток, ожидающий блокировки объекта, не реагирует на прерывание? я провел поиск и прочитал прерывание заблокированного потока. Я понимаю аргументы, как в java, только методы могут быть принудительно генерированы исключениями, а синхронизированные блоки не могут быть принудительно генерированы исключениями и т. д. Но такое поведение ожидания блокировки кажется очевидной причиной взаимоблокировок, так почему не язык Спецификация заставляет синхронизированные блоки генерировать прерванное исключение и заставлять разработчика обрабатывать его? есть ли какая-то веская причина, по которой спецификация языка не должна этого делать? Также в ответе говорится, что прерывания - это не только остановка/отмена потоков. Если это так, то почему Lock.lockInterruptably() появился позже?


person Thiru    schedule 24.02.2017    source источник
comment
Не могли бы вы опубликовать соответствующий код?   -  person Ali    schedule 24.02.2017


Ответы (1)


Весь смысл ключевого слова synchronized в том, чтобы быть простым (или, по крайней мере, настолько простым, насколько может быть многопоточность). Об этом прямо сказано в руководстве по Java по объектам Lock от Oracle:

Синхронизированный код основан на простой блокировке с повторным входом. Этот тип блокировки прост в использовании, но имеет много ограничений. Более сложные идиомы блокировки поддерживаются java.util.concurrent.locks пакет.

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

По сути, принцип разработки заключается в том, что если вам просто нужна простейшая форма взаимного исключения, synchronized подойдет; если вам нужно что-то большее, чем минимум, вам нужно использовать один из других, более сложных инструментов.

person yshavit    schedule 24.02.2017
comment
... и из-за всего этого вы должны спроектировать свой код так, чтобы ни один поток никогда не удерживал блокировку synchronized дольше, чем требуется для обновления нескольких полей. - person Solomon Slow; 24.02.2017
comment
Я согласен с ответом. Меня не смущает поведение. Чего я не понял, так это того, что это поведение «навсегда попытаться заблокировать», казалось, приводило к легким взаимоблокировкам и отсутствию восстановления. Я не могу дождаться тайм-аута и прерывания. Если это очевидный источник взаимоблокировок, то разработчики языка подумали бы о выходе из этого. Одним из решений, которое я мог придумать, было прерывание (при условии, что прерывание - лучший способ остановить поток). Я хотел понять, была ли веская причина, по которой языковой дизайн не дал решения этой проблемы ранее. Или может быть мои предположения неверны. - person Thiru; 25.02.2017
comment
Ну, во-первых, это может привести только к тупиковой ситуации, когда вы получаете доступ к нескольким замкам одновременно. И разработчики языка придумали выход из этого положения: вышеупомянутые более сложные конструкции. Во многих случаях все, что вам нужно, — это простой способ задать некоторые поля атомарно или что-то подобное простое, и в таких случаях приятно иметь простую конструкцию, которая делает именно то, что вам нужно, и не более того. - person yshavit; 25.02.2017
comment
Вот еще один способ подумать об этом. Эта способность прерывания, которую вы хотите, как бы она выглядела? Если вас беспокоят взаимоблокировки, значит, вы имеете дело с несколькими блокировками и вам нужен способ указать, какую из них вы хотите использовать, например, ссылку на объект. Затем вам нужно указать, как его получить: обычный, прерываемый, с тайм-аутом и т. д. - звучит как вызов метода. Затем вам нужно всегда отпускать его - звучит как попытка-наконец-то. Так что ваш более продвинутый synchronized начинает очень походить на объект Lock с try-finally. - person yshavit; 25.02.2017
comment
извините, что тяну это дольше, просто пытаясь понять - скажем, если спецификация языка заставляет каждый синхронизированный блок покрываться блоком try-catch, перехватывающим InterruptedException, и JVM выдает это исключение для ожидающего потока при прерывании во время ожидания, это можно было бы решить раньше? в чем проблема с этим подходом? - person Thiru; 04.04.2017
comment
В этом нет внутренней проблемы. Это просто более сложный вариант использования, и он усложнит даже простое использование. Как только разработчики JLS узнали, что будут простые варианты использования (например, просто запись в несколько полей, но делать это атомарно) и сложные варианты использования (с использованием классов Object.wait и т. д., а затем классов java.util.concurrent.* в качестве промежуточного уровня сложности). Так что им пришлось где-то подвести черту под простым случаем — и они выбрали полный мьютекс, без возможности прерывания. Могли ли они выбрать что-то другое? Конечно. Это был приговор. - person yshavit; 04.04.2017