Я изучал идиому блокировки с двойной проверкой и, насколько я понял, ваш код может привести к проблеме чтения частично созданного экземпляра, ЕСЛИ ваш класс Test не является неизменным:
Модель памяти Java предлагает специальную гарантию безопасности инициализации для совместного использования неизменяемых объектов.
К ним можно безопасно обращаться, даже если синхронизация не используется для публикации ссылки на объект.
(Цитаты из очень рекомендуемой книги Java Concurrency in Practice)
Так что в этом случае идиома блокировки с двойной проверкой будет работать.
Но, если это не так, обратите внимание, что вы возвращаете экземпляр переменной без синхронизации, поэтому переменная экземпляра может быть построена не полностью (вы увидите значения атрибутов по умолчанию вместо значений, предоставленных в конструкторе ).
Булева переменная ничего не добавляет, чтобы избежать проблемы, потому что она может быть установлена в true до инициализации класса Test (ключевое слово synchronized не предотвращает переупорядочение полностью, некоторые выражения могут изменить порядок). В модели памяти Java нет правила «до того, как это произойдет».
И создание логической переменной volatile также ничего не добавит, потому что 32-битные переменные создаются атомарно в Java. Идиома блокировки с двойной проверкой будет работать и с ними.
Начиная с Java 5, вы можете исправить эту проблему, объявив переменную экземпляра как volatile.
Подробнее об идиоме с двойной проверкой вы можете прочитать в этой очень интересной статье .
Наконец, я прочитал несколько рекомендаций:
Подумайте, следует ли использовать шаблон синглтона. Это считается анти-паттерном для многих людей. Инъекция зависимости предпочтительнее, если это возможно. Отметьте это .
Тщательно продумайте, действительно ли необходима оптимизация блокировки с двойной проверкой перед ее реализацией, потому что в большинстве случаев это не стоило бы усилий. Кроме того, рассмотрите возможность создания класса Test в статическом поле, поскольку отложенная загрузка полезна только тогда, когда создание класса занимает много ресурсов, и в большинстве случаев это не так.
Если вам все еще нужно выполнить эту оптимизацию, проверьте ссылку , которая предоставляет некоторые альтернативы для достижения эффекта, подобного тому, что вы пытаетесь.