В JCIP у нас есть фрагмент кода, который выглядит следующим образом:
Листинг 4.2:
@ThreadSafe
public class PersonSet {
@GuardedBy("this")
private final Set<Person> mySet = new HashSet<Person>(); // line 3
public synchronized void addPerson(Person p) {
mySet.add(p);
}
public synchronized boolean containsPerson(Person p) {
return mySet.contains(p);
}
}
Мне было интересно, изменим ли мы третью строку на эту:
private Set<Person> mySet = new HashSet<Person>(); // line 3, removes final
Верно ли говорить, что класс больше не является потокобезопасным, поскольку неконечная переменная mySet
могла бы быть нулевой, даже после выхода из конструктора и публикации ссылки на экземпляр PersonSet?
Например, правда ли сказать, что такой вызывающий код может потерпеть неудачу, или я что-то неправильно понимаю? :
PersonSet p = new PersonSet();
SendToThreadB(p);
Что, если у меня есть ограничение, которое не позволяет пометить поле как "окончательное" (как, возможно, мне придется поменять его на новый экземпляр), какие существуют решения, чтобы гарантировать, что класс по-прежнему поточно-ориентирован без используя final
?