Я прочитал разные статьи, такие как дважды проверено блокировка: умно, но не работает, и я понимаю причину, по которой следующий код не работает при использовании многопоточности.
class SomeClass {
private Resource resource = null;
public Resource getResource() {
if (resource == null) {
synchronized {
if (resource == null)
resource = new Resource();
}
}
return resource;
}
}
Однако, согласно его объяснению, когда поток выходит из синхронизированного блока, он выполняет барьер записи - он должен сбрасывать любые переменные, измененные в этом блоке, в основную память, прежде чем снимать блокировку. Следовательно, когда поток A сталкивается с синхронизированным блоком, а затем выполняет следующий процесс по порядку:
- Будет выделена память для нового объекта Resource;
- будет вызван конструктор для ресурса,
- инициализация полей-членов нового объекта;
- ресурсу поля SomeClass будет присвоена ссылка на вновь созданный объект
Наконец, прежде чем поток A выйдет из синхронизированного блока, он запишет свой локальный объект ресурса обратно в основную память, а затем поток B прочитает этот вновь созданный ресурс из основной памяти, как только он попадет в синхронизированный блок.
Почему поток B может видеть эти операции с памятью в другом порядке, чем выполняется одним потоком A? Я думал, что поток B не будет знать, что объект ресурса создан, пока поток A не сбрасывает свою локальную память в основную память когда он выходит из синхронизированного блока, потому что поток B может читать объект ресурса только из разделяемой основной памяти?
Пожалуйста, поправьте мое понимание .... Спасибо.