Синхронизированный блок — Java

#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 завершается внезапно по той же причине.