ВАЖНОЕ РЕДАКТИРОВАНИЕ. Я знаю о "происходит до" в потоке, в котором выполняются два назначения, мой вопрос: возможно ли это для другого потока читать «b» не равным нулю, пока «а» все еще равно нулю. Итак, я знаю, что если вы вызываете doIt () из того же потока, что и тот, где вы ранее вызывали setBothNonNull (...), тогда он не может вызвать исключение NullPointerException. Но что, если один вызывает doIt () из другого потока, чем тот, который вызывает setBothNonNull (...)?
Обратите внимание, что этот вопрос касается исключительно ключевого слова volatile
и volatile
гарантий: он не относится к ключевому слову synchronized
(поэтому, пожалуйста, не отвечайте «вы должны использовать синхронизацию», потому что у меня нет никаких проблем для решения: я просто хочу понять volatile
гарантии (или отсутствие гарантий) в отношении исполнения вне очереди).
Скажем, у нас есть объект, содержащий две ссылки volatile
String, которые инициализируются конструктором значением null, и что у нас есть только один способ изменить эти две String: вызовом setBoth (...) и что мы можем только впоследствии устанавливайте свои ссылки на ненулевые ссылки (только конструктору разрешено устанавливать их в null).
Например (это всего лишь пример, вопросов пока нет):
public class SO {
private volatile String a;
private volatile String b;
public SO() {
a = null;
b = null;
}
public void setBothNonNull( @NotNull final String one, @NotNull final String two ) {
a = one;
b = two;
}
public String getA() {
return a;
}
public String getB() {
return b;
}
}
В setBothNoNull (...) строка, назначающая ненулевой параметр «a», появляется перед строкой, назначающей ненулевой параметр «b».
Затем, если я сделаю это (опять же, нет вопросов, следующий вопрос):
doIt() {
if ( so.getB() != null ) {
System.out.println( so.getA().length );
}
}
Правильно ли я понимаю, что из-за неупорядоченного выполнения я могу получить NullPointerException?
Другими словами: нет никакой гарантии, что, поскольку я прочитал ненулевое значение «b», я прочту ненулевое значение «а»?
Потому что из-за неисправного (мульти) процессора и способа работы volatile
"b" может быть поставлено перед "a"?
volatile
гарантирует, что при чтении после записи всегда будет отображаться последнее записанное значение, но здесь есть "проблема" вне очереди, верно? (еще раз, «проблема» сделана с целью попытаться понять семантику ключевого слова volatile
и модели памяти Java, а не для решения проблемы).
a
будет назначен доb
, тогда возможно получить ненулевоеb
и все равно получить нулевоеa
. Какие гарантии есть сvolatile
? Действительно хороший вопрос +1. - person kiwicptn   schedule 14.03.2010