Почему DCL без volatile действует для примитивов? - PullRequest
1 голос
/ 19 сентября 2019

Отказ от ответственности: Я не использую DCL в реальном производственном коде - у меня есть только академический интерес.

Я прочитал следующую известную статью: "ДвойнойПроверено, что блокировка сломана »Декларация

Декларация проблемы (мое видение):

// Correct multithreaded version
class Foo { 
  private Helper helper = null;
  public synchronized Helper getHelper() {
    if (helper == null) 
        helper = new Helper();
    return helper;
    }
  // other functions and members...
  }

Давайте представим, что thread_1 выполненная строкаhelper = new Helper(); Другой поток (thread_2) might видит, что ссылка helper не пуста, но еще не инициализирована.Это происходит из-за того, что вызов конструктора может быть переупорядочен с helper назначением ссылки из thread_2 veiw.

Но в этой статье упоминалось, что этот подход работает правильно для 32-битных примитивов.

Хотя идиома блокировки с двойной проверкой не может использоваться для ссылок на объекты, она может работать для 32-битных примитивных значений (например, int или float).Обратите внимание, что он не работает для long или double, так как несинхронизированное чтение / запись 64-битных примитивов не гарантированно является атомарным.

// Correct Double-Checked Locking for 32-bit primitives
class Foo { 
  private int cachedHashCode = 0;
  public int hashCode() {
    int h = cachedHashCode;
    if (h == 0) 
    synchronized(this) {
      if (cachedHashCode != 0) return cachedHashCode;
      h = computeHashCode();
      cachedHashCode = h;
      }
    return h;
    }
  // other functions and members...
  }

Пожалуйста, объясните мне, почему это работает?Я знаю, что 32-битная запись является атомарной.

В чем здесь причина локальной переменной?

1 Ответ

1 голос
/ 19 сентября 2019

Суть «DCL сломан» состоит в том, что, используя DCL для инициализации одноэлементного объекта, поток может увидеть ссылку на объект, прежде чем он увидит объект в полностью инициализированном состоянии.DCL адекватно синхронизирует фактически конечную глобальную переменную, которая ссылается на синглтон, но ему не удается синхронизировать одноэлементный объект, на который ссылается глобал.

В вашем примере есть только глобальная переменная.Нет «объекта, к которому он относится».

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...