Ну, обе реализации могут быть статическими, так что это первое недоразумение. Ведущий в этом видео объясняет, как можно использовать безопасность потоков при инициализации класса.
Инициализация класса по своей сути поточно-ориентирована, и, если вы можете инициализировать объект при инициализации класса, создание объекта тоже поточно-ориентировано.
Вот пример поточно-ориентированного статически инициализированного объекта
public class MySingletonClass{
private MySingletonClass(){
}
public static MySingletonClass getInstance(){
return IntiailizationOnDemandClassholder.instance;
}
private static class IntiailizationOnDemandClassHolder{
private static final MySingletonClass instance = new MySingletonClass();
}
}
Что важно знать здесь, переменная экземпляра MySingletonClass никогда не будет создана и / или инициализирована до тех пор, пока не будет вызван getInstance()
. И снова, поскольку инициализация класса является поточно-ориентированной, переменная instance
, равная IntiailizationOnDemandClassholder
, будет загружена безопасно, один раз и видима для всех потоков.
Ответ на ваши изменения зависит от вашего другого типа реализации. Если вы хотите сделать двойную проверку-блокировку, переменная вашего экземпляра должна быть изменчивой. Если вы не хотите использовать DCL, вам нужно будет каждый раз синхронизировать доступ к вашей переменной. Вот два примера:
public class DCLLazySingleton{
private static volatile DCLLazySingleton instance;
public static DCLLazySingleton getInstace(){
if(instance == null){
synchronized(DCLLazySingleton.class){
if(instance == null)
instance=new DCLLazySingleton();
}
}
return instance;
}
и
public class ThreadSafeLazySingleton{
private static ThreadSafeLazySingleton instance;
public static ThreadSafeLazySingleton getInstance(){
synchronized(ThreadSafeLazySingleton.class){
if(instance == null){
instance = new ThreadSafeLazySingleton();
}
return instance;
}
}
Последний пример требует получения блокировки при каждом запросе экземпляра. Второй пример требует volatile-чтения для каждого доступа (может быть дешевым или нет, зависит от процессора).
Первый пример всегда блокируется один раз, независимо от процессора. Не только это, но и каждое чтение будет нормальным без необходимости беспокоиться о безопасности потоков. Мне лично нравится первый пример, который я перечислил.