#java #multithreading #mutex
#java #многопоточность #мьютекс
Вопрос:
Я понимаю, что синхронизированный блок, предоставляемый в Java, по сути, является реализацией мьютекса повторного входа. Однако является ли синхронизированный блок атомарным?
Итак, как обрабатываются прерывания для потоков, выполняемых в данный момент в синхронизированном блоке — просто ли он снимает блокировку, отменяя все изменения, внесенные до сих пор?
РЕДАКТИРОВАТЬ: что касается части вопроса о прерываниях — как это обычно обрабатывается в Java. Например, я вижу много примеров кода Java, в которых разработчики перехватывают прерывание, когда (скажем) поток находится в очереди ожидания. Однако в блоке catch все, что они делают, это выводят сообщение о возникновении прерывания. Мне больше любопытно, что на самом деле происходит с этим потоком? Удален ли он из очереди ожидания?
Ответ №1:
— атомарность
Синхронизированные блоки помогают реализовать атомарность, но их операции с данными не могут быть гарантированно атомарными. Чтобы сделать материал в синхронизированном блоке атомарным, вы часто используете атомарные структуры данных, такие как геттеры и сеттеры, например, AtomicBoolean .
Существует множество отличных атомарных классов, таких как атомарные массивы int, поддерживаемые последней версией java.
— как обрабатываются прерывания :
Прерывания явно не обрабатываются синхронизацией — только синхронные блоки гарантируют, что во время выполнения блок не может быть повторно введен другим потоком.
Ответ №2:
Однако является ли синхронизированный блок атомарным?
Да, синхронизированный блок обеспечивает, чтобы этот блок и любой блок, синхронизированный с одним и тем же объектом, были атомарными.
Как обрабатываются прерывания:
Прерывания полностью отличаются от синхронизации в Java. У каждого потока есть interruptedStatus
флаг, который устанавливается всякий раз, когда вы вызываете interrupt()
поток. Такие методы, как Thread.sleep()
выдача исключения InterruptedException, если установлен флаг прерывания, и останавливают их спящий режим.
Обратите внимание, что Thread.sleep()
это не отменяет никаких блокировок во время периода ожидания. Блокировка, связанная с синхронизированным блоком, снимается только тогда, когда выполнение выходит из блока.
Комментарии:
1. Итак, в основном программист должен перехватить событие прерывания и отменить блокировку, если оно находится внутри синхронизированного блока?
2. @Titan Синхронизированный блок более эквивалентен блокировке с ограниченной областью, поэтому снятие блокировки выполняется просто путем выхода из этой области. Обратите внимание, что события прерывания — это просто механизм для управления потоками низкого уровня — хотя они могут использоваться в одно и то же время, они являются ортогональными понятиями.
Ответ №3:
Итак, в основном программист должен перехватить событие прерывания и отменить блокировку, если оно находится внутри синхронизированного блока?
Вам не нужно обрабатывать блокировку. Как написано в JLS 14.18 , оператор synchronized:
Если выполнение блока завершается нормально, блокировка разблокирована, и оператор synchronized завершается нормально. Если выполнение блока внезапно завершается по какой-либо причине, блокировка разблокирована, и затем оператор synchronized завершается внезапно по той же причине.