Синхронизированный блок защищает весь кодовый блок. Синхронизированный метод защищает полный код метода. В обоих случаях синхронизированный относится к объекту, который он использует в качестве монитора - либо this
(или объект текущего класса), либо указанный объект.
Первое: требование для монитора объекта означает, что синхронизированное поле не может быть примитивного типа.
Второе: что должен делать синхронизированный на поле?
Есть два возможных ответа:
- защита доступа к самой ссылке XOR
- защищает доступ к объекту за ссылкой.
Первый вариант - это проблема с куриным яйцом: чтобы защитить доступ, сначала необходимо получить доступ к полю. Попробовать сделать это атомарно на мультипроцессоре может быть весело. Более того: если доступ - запись (то есть объект изменяется), тогда монитор будет на первом объекте, в то время как второй установлен ... безумие на этом пути.
Второй вариант: см. Этот кусок кода:
public class Foo {
public synchronized StringBuilder sb = ...;
public void doSomething1(){
StringBuilder sb = this.sb;
sb.append("foo");
}
public void doSomething2(){
this.sb.append("foo");
}
}
Так как только доступ будет защищен, оба метода работают одинаково. Первая версия просто проясняет, что сам вызов append
не защищен.
О, я забыл: в обоих случаях вы могли бы использовать только взаимное исключение синхронизированных - вещи wait
или notify
были бы недоступны - потому что вы не можете присоединить какой-либо фрагмент кода к переменной.
Что осталось:
Возможно просто ярлык для AtomicReference
?
Это настолько редкий случай использования, что изменение самого языка не является хорошим вариантом.