Java無鎖堆棧詳解

有這樣一個題目: 實現一個無鎖的Stack,並寫一段測試代碼(多線程訪問),證明這個Stack是線程安全的。

分析:

出於節省內存空間的考慮,使用鏈式的存儲結構來實現。
實現該堆棧的思想爲:
1、壓入一個新節點時,將舊結點存入新結點中。彈出時將頂部節點中存入的上一節點取出並將其設爲站定。
2、使用無鎖的實現類AtomicReference作爲安全的無鎖局部變量對元素進行暫存。
以下爲實現代碼,具體解釋參見注釋。

static LockFreeStack<Object> stack = new LockFreeStack<>();

    @Test
    public void test01() throws Exception {
        // 實現一個無鎖的Stack,並寫一段測試代碼(多線程訪問),證明這個Stack是線程安全的。給出程序以及運行的截圖。
        Push [] pushs = new Push[10];
        Pop [] pop = new Pop[10];
        for(int i = 0; i < 10; i++) {
            pushs[i] = new Push();
            pop[i] = new Pop();
        }
        for(int i = 0; i < 10; i++) {
            pushs[i].start();
            pop[i].start();
        }
        for(int i = 0; i < 10; i++) {
            pushs[i].join();
            pop[i].join();
        }

    }

    static class Push extends Thread {
        @Override
        public void run() {
            for(;;) {
                stack.push("Random->"+Math.random());
            }
        }
    }

    static class Pop extends Thread {
        @Override
        public void run() {
            for(;;) {
                System.out.println("已出棧:" + stack.pop());
            }
        }
    }

    static class LockFreeStack<V> {

        private AtomicReference<Node<V>> top = new AtomicReference<>();

        public LockFreeStack() {
        }

        public void push(V o) {
            Node<V> nextValue = new Node<V>(o, null);
            Node<V> oldValue = null;
            do {
                oldValue = top.get();
                nextValue.setNext(oldValue); //新節點存入舊節點
            } while (!top.compareAndSet(oldValue, nextValue));

        }

        public V pop() {
            Node<V> oldValue = null;
            Node<V> nextValue = null;
            do {
                oldValue = top.get();
                if (oldValue == null) {
                    continue;//oldValue爲空則棧內是空的
                }
                nextValue = oldValue.getNext();
                //while中oldValue == null 是指在空棧的情況下重試
            } while (oldValue == null || !top.compareAndSet(oldValue, nextValue));  
            return oldValue.getValue();
        }

        class Node<T> {
            private T value;
            private Node<T> next;

            public Node(T value, Node<T> next) {
                super();
                this.value = value;
                this.next = next;
            }

            public T getValue() {
                return value;
            }

            public void setValue(T value) {
                this.value = value;
            }

            public Node<T> getNext() {
                return next;
            }

            public void setNext(Node<T> next) {
                this.next = next;
            }

        }

    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章