1. 程式人生 > >(轉)利用CAS算法實現通用線程安全狀態機

(轉)利用CAS算法實現通用線程安全狀態機

多線程 實例對象 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算法實現通用線程安全狀態機