Одноэлементная блокировка двойной проверки Java должна использовать ключевое слово volatile?

привет, у меня проблема с двойной проверкой блокировки в одноэлементном шаблоне。 в следующем коде:

private volatile   static DoubleCheckSingleton instance;

private DoubleCheckSingleton() {}


public static DoubleCheckSingleton getInstance(){

    if(instance==null){ //first

        synchronized (DoubleCheckSingleton.class){

            if(instance==null){  // second
                instance=new DoubleCheckSingleton();
            }

        }

    }

    return instance;

}

Предположим, что теперь есть два потока, A и B соответственно. После этого они выполняются одновременно. Согласно определению «происходит-прежде» после того, как один поток снимает блокировку, другой поток получает блокировку, после чего последний может увидеть предыдущее изменение.

Если это так, я не думаю, что ключевое слово volatile необходимо, так почему мы должны использовать его здесь? Какой друг может объяснить это? Спасибо за ваш ответ


person Qin Dong Liang    schedule 04.07.2018    source источник
comment
Я не понимаю, что вы имеете в виду, вы можете объяснить это подробно?   -  person Qin Dong Liang    schedule 04.07.2018
comment
это просто академический вопрос? В противном случае вам следует взглянуть на идиому держателя инициализации-по-запросу.   -  person dpr    schedule 04.07.2018
comment
Вероятно, используйте static-holder-class-шаблон, упомянутый здесь   -  person Lino    schedule 04.07.2018
comment
Мой вопрос заключается в том, зачем вам нужно ключевое слово volatile, если у вас есть правило «происходит до». @все   -  person Qin Dong Liang    schedule 04.07.2018
comment
происходит до того, как вступает в силу ключевое слово synchronized, которое происходит после того, как вы оценили if. Это if не определяет какое-либо свойство «происходит до», если переменная не является изменчивой, и поэтому эффекты произвольны.   -  person kumesana    schedule 04.07.2018
comment
Согласно определению «происходит до того, как» после того, как один поток снимает блокировку, другой поток получает блокировку, после чего последний может видеть предыдущее изменение. Поскольку вы можете видеть изменения, зачем вам ключевое слово volatile? @kumesana   -  person Qin Dong Liang    schedule 04.07.2018
comment
Проблема без ключевого слова volatile заключается в том, что вы можете видеть изменения, когда они происходят. Не бывает-раньше правил говорящих об обратном. Таким образом поток может прийти туда и увидеть ненулевой экземпляр, пока он строится и абсолютно не готов к использованию. Тем не менее, этот поток не попадет в if и начнет использовать экземпляр, который не готов к использованию.   -  person kumesana    schedule 04.07.2018
comment
Я все еще не понимаю, что вы имеете в виду. Вот синхронизированное ключевое слово. Во второй нулевой проверке приведенного выше кода, если есть правило «случилось до», после того, как поток A снимает блокировку, поток B может видеть, что экземпляр не является нулевым, тогда я действительно не понимаю, почему синглтону также нужен использовать volatile для обеспечения видимости. @kumesana   -  person Qin Dong Liang    schedule 04.07.2018
comment
Я говорю вам, что проблема не в том, чтобы гарантировать, что поток B сможет увидеть полностью построенный объект. Проблема заключается в том, чтобы гарантировать, что thead B не сможет увидеть ненулевой объект, который не полностью построен. Если это так, то первая нулевая проверка говорит B, что не нужно заботиться о синхронизации, и поэтому не имеет значения, что вы пытались выполнить синхронизацию.   -  person kumesana    schedule 04.07.2018
comment
Верен ли приведенный выше код, если ключевое слово volatile отсутствует? @kumesana   -  person Qin Dong Liang    schedule 04.07.2018
comment
@QinDongLiang, если первое условие ложно, нет синхронизации, нет барьера памяти, и поток может видеть объект, который не был инициализирован должным образом.   -  person Peter Lawrey    schedule 04.07.2018
comment
без volatile это неправильно.   -  person Peter Lawrey    schedule 04.07.2018
comment
Как я уже сказал, он предоставит вызывающим метод getInstance() экземпляр DoubleCheckSingleton, над которым в настоящее время работает поток, который его создает. Это определенно неправильно. Такой экземпляр находится в недопустимом состоянии, и его использование нарушит все ожидания.   -  person kumesana    schedule 04.07.2018
comment
В соответствии с определением «происходит до» синхронизированный блок кода гарантирует, что следующий поток, который получит блокировку, сможет увидеть последние изменения, что соответствует ключевому слову volatile. Если то же самое, ключевое слово volatile здесь не нужно. @kumesana   -  person Qin Dong Liang    schedule 04.07.2018
comment
Вы по-прежнему не можете рассмотреть следующий поток, который не получает блокировку, потому что он не пытается получить блокировку.   -  person kumesana    schedule 04.07.2018
comment
@kumesana доброе утро. Давайте продолжим обсуждение。 Почему следующий поток не получит блокировку?   -  person Qin Dong Liang    schedule 05.07.2018
comment
Привет. Следующий поток достигает первой нулевой проверки и видит ненулевую переменную. Из-за этого он не попадает в if и, следовательно, не участвует в синхронизированном блоке. Без синхронизированного блока нет блокировки, которую можно было бы попытаться получить. Поскольку у него нет блокировки, которую можно попытаться получить, он не получит ту блокировку, которой не существует.   -  person kumesana    schedule 05.07.2018
comment
@kumesana Следующий поток, если нет связи «происходит до», он не может видеть изменения, поэтому он может видеть только нулевые значения. Что вы думаете? кстати в какой ты стране. Рад встрече .   -  person Qin Dong Liang    schedule 05.07.2018
comment
Давайте продолжим обсуждение в чате.   -  person kumesana    schedule 05.07.2018
comment
привет @kumesana что ты делаешь? у меня новая проблема, нужна твоя помощь   -  person Qin Dong Liang    schedule 06.07.2018
comment
@kumesana в ключевом слове sychionized java может предотвратить изменение порядка кода?   -  person Qin Dong Liang    schedule 06.07.2018
comment
@QinDongLiang, конечно, как часть обеспечения отношений «случается до».   -  person kumesana    schedule 06.07.2018