abstract class AbstractFoo {
private int x, y; // Our state
// This enum and field are used to track initialization
private enum State {
NEW, INITIALIZING, INITIALIZED
};
private final AtomicReference<State> init = new AtomicReference<State>(
State.NEW);
public AbstractFoo(int x, int y) {
initialize(x, y);
}
// This constructor and the following method allow
// subclass's readObject method to initialize our state.
protected AbstractFoo() {
}
protected final void initialize(int x, int y) {
if (!init.compareAndSet(State.NEW, State.INITIALIZING))
throw new IllegalStateException("Already initialized");
this.x = x;
this.y = y;
// ...Do anything else the original constructor did
init.set(State.INITIALIZED);
}
// These methods provide access to internal state so it can
// be manually serialized by subclass's writeObject method.
protected final int getX() {
checkInit();
return x;
}
protected final int getY() {
checkInit();
return y;
}
// Must call from all public and protected instance methods
private void checkInit() {
if (init.get() != State.INITIALIZED)
throw new IllegalStateException("Uninitialized");
}
}
我困惑的是使用
AtomicReference
。他的解释是:请注意,initialized字段是原子引用(java.util.concurrent.atomic.AtomicReference)。这是必要的,以确保在面对决心敌人时对象完整性。如果没有这个预防措施,如果一个线程在实例上调用initialize,而第二个线程试图使用它,则第二个线程可能会看到不一致状态的实例。
我不理解这如何增强对象安全性,以避免在不一致状态下使用它。在我的理解中,如果一个线程运行了
initialize()
,第二个线程运行任何访问器,那么在将初始化标记为完成之前,第二个线程不可能读取x或y字段的值。我可能看到的另一个可能问题是
AtomicReference
应该是线程安全的(可能有volatile字段内部)。这将确保在init
变量中的值更改与其他线程立即同步,从而防止在初始化已完成但执行访问器方法的线程无法看到它时获取IllegalStateException。但这是作者所说的吗?我的推理正确吗?还是有其他解释?