Само Java 5 и по-нова версия. Да приемем многопроцесорен компютър със споделена памет (вероятно използвате такъв в момента).
Ето код за ленива инициализация на сингълтън:
public final class MySingleton {
private static MySingleton instance = null;
private MySingleton() { }
public static MySingleton getInstance() {
if (instance == null) {
synchronized (MySingleton.class) {
if (instance == null) {
instance = new MySingleton();
}
}
}
return instance;
}
}
Трябва ли instance
да се декларира volatile
, за да попречи на оптимизатора да пренапише getInstance(), както следва (което би било правилно в последователна програма):
public static MySingleton getInstance() {
if (instance == null) {
synchronized (MySingleton.class) {
// instance must be null or we wouldn't be here (WRONG!)
instance = new MySingleton();
}
}
}
Ако приемем, че оптимизаторът не пренаписва кода, ако instance
не е деклариран, volatile
все още ли е гарантирано, че ще бъде изчистен в паметта, когато се излезе от блока synchronized
, и ще се прочете от паметта, когато се влезе в блока synchronized
?
РЕДАКТИРАНЕ: Забравих да направя getInstance() статичен. Не мисля, че това променя валидността на отговорите; всички знаехте какво имах предвид.
javap -c com.example.ClassName
, за да разглобите кода, така че да можете да проверите как е бил компилиран и дали компилаторът е променил/оптимизирал едното или другото. Проверих го за вас с този на JDK 1.6 и компилаторът не премахна вложенотоif
. - person BalusC   schedule 30.08.2010