Объявление синхронизированных полей работает только с примитивными типами в Java.Нельзя синхронизировать объекты, просто объявив их ссылки синхронизированными - представьте, что произойдет, если вы попытаетесь сделать две разные ссылки на один и тот же объект.
Таким образом, вы можете понять, почему следующий синтаксис не разрешен:
public ArrayList<Object> myList = new ArrayList<Object>();
public synchronized ArrayList<Object> mySyncedList = myList;
//is the original list now synchronized or not?
Хотя у вас есть несколько решений для этого:
1) Если у вас есть доступ к исходному исходному коду, вы можете вручную синхронизировать его, то есть синхронизировать все мутаторы так,что никаких проблем теоретически не может возникнуть.Это может быть сложно, если класс сложный, но, по крайней мере, вы гарантированно, что везде, где этот класс используется, он синхронизируется.
public class MyCollection {
public synchronized void addObject(Object a) {
...
}
}
В частности, класс Vector
внутренне синхронизирован и в вашемНапример, не нужно больше синхронизировать.Однако ваши собственные классы и многие классы Java не будут иметь такой гарантии.
2) Если Объект является классом библиотеки Java, может быть способ получить синхронизированную копию с использованием функциональных возможностей библиотеки.Чаще всего это используется для списков:
public List<Object> mySyncedList = Collections.synchronizedList(myList);
//pass around mySyncedList instead of myList to guarantee synchronization
3) Если объект не синхронизирован изнутри, и не предоставляет возможность получить его синхронизированную копию, и у вас нет возможности редактироватьИсходный исходный код, у вас нет выбора, кроме как синхронизировать код, который изменяет объект:
synchronized(myList) {
myList.add(next);
}
Осторожно, хотя: даже если ваш собственный код синхронизирован, если вы публикуете ссылку на этот объект снаружитогда любой программист, использующий ваши классы, также должен будет синхронизировать доступ к этому объекту!