(轉)利用CAS算法實現通用線程安全狀態機
阿新 • • 發佈:2017-10-09
多線程 實例對象 urn 安全 con 如果 oct 模式 cat
在多線程環境下,如果某個類是有狀態的,那我們在使用前,需要保證所有該類的實例對象狀態一致,否則會出現意向不到的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算法實現通用線程安全狀態機