В Параллелизм Java на практике приведен пример *, демонстрирующий проблему видимости , когда два разных потока могут не видеть досостояние даты любого конкретного изменяемого объекта из-за отсутствия синхронизации.
public class Holder {
private int n;
public Holder(int n) { this.n = n; }
public void assertSanity() {
if (n != n){
throw new AssertionError("This statement is false.");
}
}
В этом конкретном примере книга заявляет, что поток «А» должен сначала инициализироваться и опубликовать его через небезопасный поток, например:
public Holder holder;
public void initialize() {
holder = new Holder(42);
}
А затем поток "B" вызывает holder.assertSanity()
, что вполне возможно, что AssertionError
будет брошен из-за несовместимого состояния.
Теперь,Я понимаю основную предпосылку аргумента, когда изменение, сделанное в изменяемой переменной, никогда не может наблюдаться другим потоком.Но что меня смущает, так это то, что он сравнивает одну и ту же (или я так думаю) ссылку n != n
.
Разве это не сравнивает значение изменяемого примитивного поля private int n
?Независимо от того, что n
теперь может иметь значение 42 для потока A и значение 0 (по умолчанию) для потока B, не должен быть прямой вызов для проверки его значения в том же потоке *1023*. соответствует ?т. е. вызов assertSanity()
в потоке A проверит, если 42 != 42
, а в потоке B 0 != 0
?
* Ссылка на 3.5 Safe Publication, листинги 3.14 и 3.15 в книге.