2017-01-28 2 views
0

Я хочу знать, что такое использование переменной Instance как изменчивой в двойной нулевой проверке реализации Singleton. Потому что в соответствии с моим пониманием синхронизация блока обеспечивается до неявного. Ни один из двух потоков не может получить доступ к этому синхронизированному блоку одновременно, а при выходе из синхронизированного блока поток записывает все свои локальные кэшированные данные в основную память. Я много искал, но все же у меня есть сомнения в этой реализации. Пожалуйста, объясните правильное использование.Использование volatile в singleton double null check реализация в java

private volatile Singleton INSTANCE; 
public Singleton get() { 
    if (INSTANCE == null) { 
     synchronized (this) { 
      if (INSTANCE == null) { 
       INSTANCE = new Singleton(); 
      } 
     } 
    } 
    return INSTANCE; 
} 

В вышеуказанном двойном контрольном коде. Что может быть проблемой, если я не сделаю свой экземпляр нестабильным. Потому что, когда первый поток входит в блок синхронизации, ни один другой поток не получит доступ к этому блоку. И когда первая нить покидает этот блок. Объект будет создан и должен произойти до свойства, последнее значение экземпляра будет записано в основной памяти. Итак, почему волатильность важна в этом сценарии?

Здесь есть ссылка (Is there any need to add volatile keyword to guarantee thread-safe singleton class in java?). Но ответы не очень ясны. Я не думаю, что в данном сценарии выше любой вид оптимизации JVM может привести к разрыву происходит перед из Синхронизировать блок

+2

Покажите нам код, о котором вы говорите, и покажите нам, что именно происходит - прежде чем вы говорите. Тогда мы можем это объяснить. –

+0

(Это, вероятно, дубликат, но без каких-либо подробностей будет сложно выбрать лучшего дубликата.) –

+0

Пожалуйста, внесите это в вопрос. –

ответ

0

volatile Важен здесь из-за внутренних компонентов JVM на уровне байт-кода. Заявление

INSTANCE = new Singleton() 

находится на уровне байт-кода на самом деле что-то вроде этого:

1. INSTANCE = create Singleton object 
2. call constructor of INSTANCE 

если INSTANCE является volatile виртуальная машина гарантирует Вам, что 1 + 2 выполнены как атомарная операция с точки зрения другого потоки, например сохраняя экземпляр в стеке перед его сохранением в поле. Если это неvolatile может быть, что другие темы уже могут см. ссылка на Singleton до того, как был вызван конструктор. Таким образом, эти потоки могут видеть неполный объект.

0

Поскольку согласно моему Синхронизировать блок понимания обеспечения происходит прежде, чем неявно. Ни один из двух потоков не может получить доступ к этому синхронизированному блоку одновременно и при выходе из синхронизированного блока

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

private Singleton INSTANCE; 

public static synchronized Singleton getInstance() { 
    if (INSTANCE == null) { 
    INSTANCE = new Singleton(); 
    } 
    return INSTANCE; 
} 

Но как только у вас есть безопасная двойная проверка ленивой реализации, не каждый путь кода проходит через синхронизированный блок. Второй вызов этого метода будет читать переменную из локального поля без ввода блока synchronized, а INSTANCE должен быть изменчивым.

private volatile Singleton INSTANCE; 

public Singleton get() { 
    if (INSTANCE == null) { 
    synchronized (this) { 
     if (INSTANCE == null) { 
     INSTANCE = new Singleton(); 
     } 
    } 
    } 
    return INSTANCE; 
} 

Подробнее о безопасной публикации вы можете узнать в this article.

Смежные вопросы