Pull to refresh

Comments 9

Double Checking не работает. После первой проверки на null, мы можем получить ссылку на недоинициализированный объект.

Именно поэтому, чтобы такого не произошло, там стоит синхронизация на классе. После входа этот блок, все параллельные потоки не смогут получить доступ к полю instance, до завершения этого блока.

Могут.

Часть метода выглядит под капотом работает так:

instance = malloc();
instance.ctor();

Второй поток сделает первую проверку на null и получит не до конца сконструированный объект.

Работает. После первой проверки, если объект ещё не создан, мы попадаем в блок с синхронизацией, которая гарантированно будет выполняться одновременно только в одном потоке. Те даже если два потока одновременно запросят экземпляр объекта, любой первый кто дошел до синхронизации его создаст и инициализирует, затем положит его в переменную, а у второго потока в переменной уже не будет null, из за чего он пропустит его создание, и просто вернёт уже созданный объект.

Синхронизация не даст два раза сконструтировать объект, но не запретит получить ссылку на не до конца сконструированный объект.

Дополню: The Java memory model allows the publication of partially initialized objects and this may lead in turn to subtle bugs.

В таком случае при создании любого объекта, при попытке его использования мы можем получить не до конца сконструированный объект?

В теории да, можно создать не до конца инициализированный объект... через байт-код, если не вызвать его конструктор, но через сам код на java такие приколы сделать не получится.

Double Checking существует уже очень давно, и я думаю не просто так

Согласен с rmrfchik: DCL является антипаттерном. Об этом есть отдельный раздел 16.2.4 в изветсной книге с поездами. Тут как раз второй поток может наблюдать либо неинициаоизированный объект, либо объект в неконсистентном состоянии, т.е. часть полей инициализировано. И чтобы все работало нужно еще volatile добавить!!! Плюсом java > 5.

Sign up to leave a comment.