Да, может. Обратите внимание, что вы синхронизируете на том же объекте, который вы устанавливаете . Таким образом, установщик может изменить ссылку на объект на что-то другое, тогда получатель может синхронизироваться на новом объекте, пока установщик все еще находится внутри синхронизированного блока.
Но есть и другое: flag
- это (обычно) ссылка на один из общесистемных синглетонов Boolean.TRUE
и Boolean.FALSE
, поэтому (по крайней мере теоретически) можно заблокировать их вне вашего класса даже без ссылки на ваш класс. В этом случае вы можете зайти в тупик, и вам будет трудно понять, почему.
(Обратите внимание, что код в его текущей форме является неправильным, так как установщик не имеет параметра, поэтому this.flag = flag
присваивает ссылку себе - но выше я предполагаю, что вы имели в виду, что он ведет себя как обычный установщик:)
Исправление заключается в использовании выделенного private final
объекта блокировки (в случае, если вы хотите абсолютно гарантировать, что никто снаружи не сможет синхронизироваться с той же блокировкой, которую вы используете в своем классе - что, я полагаю, было вашим первоначальным намерением): 1014 *
public MyClass{
private final Object lock = new Object();
private Boolean flag = false;
public Boolean getflag(){
synchronized(lock){
//BLOCK 1
return flag;
}
}
public void setflag(Boolean flag){
synchronized(lock){
//BLOCK 2
this.flag = flag;
}
}
}
Если вас не очень беспокоит другая синхронизация с той же блокировкой, которую вы используете внутри, вы можете просто сделать ваши методы synchronized
(в этом случае они блокируются на this
).