java.util.concurrent.CopyOnWriteArrayList如何實現實現寫入的線程安全性

CopyOnWriteArrayList和CopyOnWriteArraySet也是線程安全的集合,其中所有的修改線程對底層數組進行復制。當線程對其讀,直接讀取集合本身無需加鎖和阻塞;當線程對其寫入(包括調用add,remove,set等方法),該集合會在底層複製一份數組,接下來對數組進行寫入操作。由於對其寫入都是對數組副本的操作,因此是線程安全的。由於每次寫入都要複製數組會導致性能很差,因此適合讀操作遠大於寫入的場景,例如緩存。

具體源碼:

/**
     * Appends the specified element to the end of this list.
     *
     * @param e element to be appended to this list
     * @return {@code true} (as specified by {@link Collection#add})
     */
    public boolean add(E e) {
        final ReentrantLock lock = this.lock;        
        lock.lock();                                            //加鎖
        try {
            Object[] elements = getArray();        //初始化一個elements變量引用原始數組
            int len = elements.length;
            Object[] newElements = Arrays.copyOf(elements, len + 1);    //利用java.util.Arrays工具方法拷貝elements
            newElements[len] = e;
            setArray(newElements);                    //將原始數組替換掉
            return true;
        } finally {
            lock.unlock();                                    //釋放鎖
        }

    }


裏面的具體函數實現:

private transient volatile Object[] array;

final Object[] getArray() {

        return array;

    }

final void setArray(Object[] a) {
        array = a;

    }


其他的remove、set方法同理,都是先加鎖,並且加的是ReentrantLock鎖,Lock和ReadWriteLock是java5的兩個根接口,併爲Lock接口提供了ReentrantLock實現類,爲ReadWriteLock接口提供了ReentrantReadWriteLock實現類,它提供了三種鎖模式:Writing、ReadingOptimistic、Reading。重入性的意思是一個線程可以對已被加鎖的ReentrantLock鎖再次加鎖,ReentrantLock對象會維持一個計數器來追蹤lock()的嵌套調用。

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