Отказ от ответственности: Я не использую 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-битная запись является атомарной.
В чем здесь причина локальной переменной?