В программах Java иногда может потребоваться отложить некоторые операции инициализации объекта с высокой головкой и инициализируются только при использовании этих объектов. Это называется отсроченной инициализацией или ленивой загрузкой
Посмотрите на небезопасную инициализацию задержки:
После потока A выполняется 1, он обнаруживает, что экземпляр объекта является нулевым и готов к новому, а поток B сначала является новым, что вызывает ошибку.
Мы можем использовать блокировки синхронизации, чтобы обеспечить правильность:
Но синхронизация всего метода слишком дорого, и люди придумали двойную блокировку:
Замок синхронизации, используемый в минимальном диапазоне, по -видимому, достигает цели с использованием двойной проверки, но это имеет проблему: когда поток 4, поток B 7 еще не выполнен, и потока A определяет экземпляр! = NULL. 7 Тема B 7 еще не выполнен, так почему это происходит?
Взгляните на базовую реализацию ключа New Encement ():
Фактически, это сначала выполнить 1 распределение памяти, затем инициализировать объект и установить экземпляр. Тогда здесь есть переупорядочение, и порядок 2 и 3 может быть заменен:
Поэтому, когда B все еще выполняет 7, A определяет в 4, что объект экземпляра был инициализирован. Если экземпляр вызван до ctorinstance (память), вызовет ошибку.
Есть два решения:
1. Объявит объект экземпляра как летучий, он запретит переупорядочить 2 и 3
2. Использование решения, основанного на инициализации класса: JVM будет выполнять инициализацию класса на стадии инициализации класса (то есть после загрузки класса и до того, как она будет использована потоком). существовать
Во время инициализации класса выполнения JVM приобретет блокировку. Эта блокировка может синхронизировать инициализацию одного и того же класса несколькими потоками
Мы обнаружим, что код реализации схемы, основанный на инициализации класса, проще. Но схема блокировки с двойной проверкой, основанная на летучих, имеет дополнительное преимущество: в дополнение к задержке инициализации статических полей, она также может задержать инициализацию полей экземпляра. Инициализация задержки поля уменьшает накладные расходы инициализации классов или создания экземпляров, но увеличивает накладные расходы на задержку инициализированных полей доступа. В большинстве случаев нормальная инициализация лучше, чем отсроченная инициализация. Если вам действительно нужно использовать поля поздней инициализации, защищенную потоком, используйте схему инициализации задержки на основе летучих действий, описанную выше; Если вам действительно нужно использовать безопасную инициализацию поток для статических полей, используйте схему инициализации на основе классов, описанную выше.
Суммировать
Выше приведено код реализации Java Double Check Lock, представленный редактором. Я надеюсь, что это будет полезно для всех. Если у вас есть какие -либо вопросы, пожалуйста, оставьте мне сообщение, и редактор ответит всем вовремя. Большое спасибо за вашу поддержку сайту wulin.com!