Спецификация языка Java определяет значение оператора synchronized
следующим образом:
Оператор synchronized
получает блокировку взаимного исключения (§17.1) дляот имени исполняющего потока, выполняет блок, затем снимает блокировку.Пока исполняющий поток владеет блокировкой, никакой другой поток не может получить блокировку.
SynchronizedStatement:`
synchronized ( Expression ) Block`
Тип выражения должен быть ссылочным типом, иначе произойдет ошибка времени компиляции.
AСинхронизированный оператор выполняется сначала путем вычисления Выражения.
Если вычисление Выражения завершается внезапно по какой-то причине, то синхронизированный оператор завершается преждевременно по той же причине.
В противном случае, если значениевыражение имеет значение null, генерируется исключение NullPointerException.
В противном случае пусть ненулевое значение выражения равно V. Выполняющий поток блокирует блокировку, связанную с V. Затем выполняется блок.Если выполнение блока завершается нормально, блокировка разблокируется, а оператор синхронизации завершается нормально.Если выполнение блока завершается внезапно по какой-либо причине, тогда блокировка разблокируется, и оператор синхронизации завершается внезапно по той же причине.
Получение блокировки, связанной с объектом, само по себе не препятствует доступу других потоковполями объекта или вызовом несинхронизированных методов объекта.Другие потоки также могут использовать синхронизированные методы или синхронизированный оператор обычным способом для достижения взаимного исключения.
То есть, в вашем примере
synchronized(this) {
listOne.add(something);
}
синхронизированный блок обрабатываетобъект упоминается listOne
любым особым образом, другие потоки могут работать с ним по своему усмотрению.Тем не менее, это гарантирует, что никакой другой поток не сможет одновременно ввести синхронизированный блок для объекта, на который указывает this
.Поэтому, если весь код, работающий с listOne
, находится в синхронизированных блоках для одного и того же объекта, не более одного потока может работать с listOne
в любой момент времени.
Также обратите внимание, что заблокированный объект не получаетспециальная защита от одновременного доступа к его состоянию, поэтому код
void increment() {
synchronized (this) {
this.counter = this.counter + 1;
}
}
void reset() {
this.counter = 0;
}
некорректно синхронизирован, поскольку второй поток может выполнить reset
, пока первый поток прочитал, но еще не записал, counter
,вызывая перезапись сброса.