標籤:medium ica exce 環境 否則 交換 ref oid 報錯
在多線程環境下,如果某個類是有狀態的,那我們在使用前,需要保證所有該類的執行個體對象狀態一致,否則會出現意向不到的bug。下面是通用安全執行緒狀態機器的實現方法。
public class ThreadSaveState{ private int x; private int y; private enum State {NEW, INITIALIZING, INITIALIZED}; private final AtomicReference<State> init = new AtomicReference<State>(State.NEW); public ThreadSaveState() { }; public ThreadSaveState(int x, int y) { initialize(x, y); } private 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); } //所有公用介面,都要先調用該方法檢測對象完整性 private void checkInit() { if (init.get() != State.INITIALIZED) { throw new IllegalStateException("Uninitialized"); } } //樣本公用介面 public int getX() { checkInit(); return x; } //樣本公用介面 public int getY() { checkInit(); return y; }}
這種模式利用compareAndSet方法來操作枚舉的原子引用,關於compareAndSet方法,其內部是CAS演算法,即:Compare and Swap, 翻譯成比較並交換,源碼如下:
java.util.concurrent包中藉助CAS實現了區別於synchronouse同步鎖的一種樂觀鎖,使用這些類在多核CPU的機器上會有比較好的效能.
結合compareAndSet源碼我們看下:
/** * Atomically sets the value to the given updated value * if the current value {@code ==} the expected value. * @param expect the expected value * @param update the new value * @return true if successful. False return indicates that * the actual value was not equal to the expected value. */ public final boolean compareAndSet(V expect, V update) { return unsafe.compareAndSwapObject(this, valueOffset, expect, update); }
根據注釋,CAS有3個運算元,記憶體值V,舊的預期值A,要修改的新值B。若且唯若預期值A和記憶體值V相同時,將記憶體值V修改為B,返回True,否則返回false。
再看看我們初始化的代碼:
if (!init.compareAndSet(State.NEW, State.INITIALIZING)) { throw new IllegalStateException("Already initialized"); }
只有當state是New的時候,才開始初始化,否則直接報錯。這就保證了對象的完整性,因為如果沒有這樣的防範機制,萬一有個線程要在某個執行個體上調用initialize(),而另一個線程又要企圖使用這個執行個體,第二個線程就有可能看到這個執行個體處於不一致的狀態。
轉載:http://blog.csdn.net/qq_27258799
(轉)利用CAS演算法實現通用安全執行緒狀態機器