Java проверил блокировку дважды

Я столкнулся с той же проблемой, когда импортировал образец кода, загруженный из Интернета. Я использую Android SDK 1.5 с плагинами 0,9 ADT. Вот более простой способ устранения проблем со ссылками на библиотеки andoid

  • Щелкните правой кнопкой мыши проект, в котором есть проблемы, и выберите свойства
  • . Выберите соответствующую сборку Android (1.1, 1.5 или 1.5 с помощью google api) и скажите «ОК»
  • Снова щелкните правой кнопкой мыши проект и выберите «Инструменты Android> Исправить свойства проекта»
  • Исправьте импорт один раз (если требуется)
  • Обновите проект, и вы должны быть готовы к работе без какого-либо ручного редактирования
39
задан GingerPlusPlus 13 February 2016 в 16:44
поделиться

5 ответов

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

РЕДАКТИРОВАТЬ: Чтобы прояснить приведенный выше ответ, исходный вопрос спросил об использовании логического значения для управления блокировкой с двойной проверкой. Без решений по ссылке выше это не сработает. Вы можете дважды проверить блокировку, фактически установив логическое значение, но у вас все еще есть проблемы с переупорядочением инструкций, когда дело доходит до создания экземпляра класса. Предлагаемое решение не работает, поскольку экземпляр может не быть инициализирован после того, как вы увидите, что инициализированное логическое значение истинно в несинхронизированном блоке.

25
ответ дан 27 November 2019 в 02:44
поделиться

Это работало бы, если бы инициализированный был изменчивым . Как и в случае с синхронизированным , интересные эффекты от volatile на самом деле не столько связаны со ссылкой, сколько с тем, что мы можем сказать о других данных. Настройка поля экземпляра и объекта Test принудительно выполняется до инициализации записи в . При использовании кэшированного значения через короткое замыкание инициализация чтение происходит до чтения экземпляра и объектов, доступных по ссылке. Нет существенной разницы в наличии отдельного инициализированного флага (кроме того, что он вызывает еще большую сложность кода).

(Правила для полей final в конструкторах для небезопасной публикации немного отличаются.)

Однако в этом случае вы должны редко видеть ошибку. Вероятность возникновения проблем при первом использовании минимальна, и это не повторяющаяся гонка.

Код слишком сложен. Вы можете просто написать это как:

private static final Test instance = new Test();

public static Test getInstance() {
    return instance;
}
16
ответ дан 27 November 2019 в 02:44
поделиться

Двойная проверка блокировки действительно нарушена, и решение проблемы действительно проще реализовать код, чем эта идиома - просто используйте статический инициализатор.

public class Test {
    private static final Test instance = createInstance();

    private static Test createInstance() {
        // construction logic goes here...
        return new Test();
    }

    public static Test getInstance() {
        return instance;
    }
}

Статический инициализатор гарантированно будет выполнен в первый раз, когда JVM загружает класс, и до того, как ссылка на класс может быть возвращена в любой поток - создание это изначально потокобезопасный.

12
ответ дан 27 November 2019 в 02:44
поделиться

Вам, вероятно, следует использовать атомарные типы данных в java.util.concurrent.atomic .

0
ответ дан 27 November 2019 в 02:44
поделиться

Это причина того, что блокировка с двойной проверкой нарушена.

Synchronize гарантирует, что только один поток может ввести блок кода. Но это не гарантирует, что изменения переменных, выполненные в синхронизированном разделе, будут видны другим потокам. Только потоки, входящие в синхронизированный блок, гарантированно увидят изменения. Это причина того, что блокировка с двойной проверкой нарушена - она ​​не синхронизируется на стороне считывателя. Поток чтения может увидеть, что синглтон не является нулем, но данные синглтона могут быть не полностью инициализированы (видимы).

Упорядочивание осуществляется с помощью volatile . volatile гарантирует упорядочение, например, запись в изменчивое статическое поле одноэлементного объекта гарантирует, что запись в одноэлементный объект будет завершена до записи в изменчивое статическое поле. Это не мешает создавать синглтон из двух объектов, это обеспечивается синхронизацией.

Статические поля final класса не обязательно должны быть изменчивыми. В Java JVM решает эту проблему.

См. Мой пост, ответ на Шаблон синглтона и сломанная блокировка с двойной проверкой в ​​реальном Java-приложении , иллюстрирующий пример синглтона по отношению к блокировке с двойной проверкой, которая выглядит умно но сломан.

5
ответ дан 27 November 2019 в 02:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: