Видимость Проблемы могут возникать, когда значение, записанное вашей программой в переменную, кэшируется в кэш процессора и не записывается в ОЗУ немедленно.По этой причине, если поток A, работающий на процессоре A, записывает значение без правильной синхронизации, а поток B считывает это значение из процессора B, он может видеть устаревшее значение в ОЗУ, а не самое последнее значение (присутствует только в кэше процессора процессора A).).
В данном примере вы не используете ни один из механизмов, предоставляемых Java для обеспечения безопасной публикации.То есть синхронизация , volatile или конечные поля установлены в конструкторе.
Поэтому можно представить, что в вашем примере ссылка на созданиеclone
объект становится доступным, но значения, записанные в поля клонов, остаются в кэше процессора.В этом случае другие потоки не смогут прочитать актуальные значения.
Чтобы дать некоторую ссылку.Посмотрите на этот пример
class FinalFieldExample {
final int x;
int y;
static FinalFieldExample f;
public FinalFieldExample() {
x = 3;
y = 4;
}
static void writer() {
f = new FinalFieldExample();
}
static void reader() {
if (f != null) {
int i = f.x;
int j = f.y;
}
}
}
Приведенный выше класс является примером того, как должны использоваться конечные поля.Читатель, выполняющий поток, гарантированно увидит значение 3 для fx, потому что оно является окончательным.Не гарантируется увидеть значение 4 для y, потому что оно не является окончательным.
Аргумент, который вы приводите, также будет иметь место для этого примера, не так ли?Экземпляр создается, поля устанавливаются в конструкторе и т. Д. Однако он не является потокобезопасным, поскольку значение, записанное в y
, не должно становиться видимым для других потоков.(Приведенный пример взят из JSR 133 (модель памяти Java) FAQ : http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html#reordering)
Обновление: Вы запросили код, демонстрирующий проблему. Я спросилпохожий (более открытый) вопрос один раз: Как продемонстрировать проблемы видимости многопоточности Java? Интересная вещь с приведенным примером кода состоит в том, что он будет вести себя по-разному с различными второстепенными версиями Java на разныхоперационные системы и другие, использующие клиент или сервер jvm . В этой связи я нашел образец весьма интересным. Важно отметить, что на самом деле может быть невозможно создать пример кода, который приведет к проблеме видимости вашегокод сегодня . Однако в следующем году поколение процессоров может реализовать другую политику кэширования, и вдруг возникнет проблема. Если вы будете следовать рекомендациям спецификации языка Java, сохраните.