Почему SafePoint threadSafe?(Параллелизм на практике)
Я читаю параллелизм на практике.
Есть следующий пример (4.3.5):
@ThreadSafe
public class SafePoint {
@GuardedBy("this") private int x, y;
private SafePoint(int[] a) { this(a[0], a[1]); }
public SafePoint(SafePoint p) { this(p.get()); }
public SafePoint(int x, int y) {
this.x = x;
this.y = y;
}
public synchronized int[] get() { return new int[] { x, y };
}
public synchronized void set(int x, int y) { this.x = x;
this.y = y;
}
}
Автор действует, что SafePoint
- Поток безопасно - я не понимаю, почему. Я не вижу, что происходит до того, как это гарантировать. После завершения конструктора другой поток может видеть SafePoint
экземпляр недооценен.
пример:
SafePoint racePublishedSafePoint; //field
//thread 1:
racePublishedSafePoint = new SafePoint(1,1);
//thread 2:
SafePoint sp;
while(true){
SafePoint sp = racePublishedSafePoint;
if(sp != null) break;
}
System.out.println(sp.get()[0]);
System.out.println(sp.get()[1]);
Я считаю, что есть несколько возможных результатов:
- приложение не заканчивается
иначе, если приложение завершено - мы можем увидеть
а) 0 0
б) 0 1
в) 1 0
г) 1 1
Я прав?
Если это правда, почему автор отметил класс как потокобезопасный? Я думал, что потокобезопасный класс - класс, который можно использовать в параллельном приложении без сложного анализа.
Что хотел сказать автор?
Также в книге я прочитал следующую заметку:
Закрытый конструктор существует, чтобы избежать состояния гонки, которое могло бы возникнуть, если бы конструктор копирования был реализован так (px, py); это пример идиомы захвата частного конструктора (Bloch and Gafter, 2005).
Это мне тоже не понятно.
зачем нам 3 конструктора и один из них приватный?
Пожалуйста, уточните эти вещи.