Двойная проверка блокировки. В общем и целом.
Парадигма, с которой я начал изучать проблемы, связанные с работой в BEA, заключается в том, что люди будут проверять синглтон следующим образом:
public Class MySingleton {
private static MySingleton s_instance;
public static MySingleton getInstance() {
if(s_instance == null) {
synchronized(MySingleton.class) { s_instance = new MySingleton(); }
}
return s_instance;
}
}
Это никогда не работает, потому что другой поток мог попасть в синхронизированный блок, а s_instance больше не равен нулю. Таким образом, естественное изменение состоит в том, чтобы сделать это:
public static MySingleton getInstance() {
if(s_instance == null) {
synchronized(MySingleton.class) {
if(s_instance == null) s_instance = new MySingleton();
}
}
return s_instance;
}
Это тоже не работает, потому что Java Memory Model не поддерживает это. Вам нужно объявить s_instance как volatile, чтобы он работал, и даже тогда он работает только на Java 5.
Люди, которые не знакомы с тонкостями модели памяти Java, все время путаются .