首頁  >  文章  >  Java  >  COW機制已經相關類別的介紹

COW機制已經相關類別的介紹

不言
不言轉載
2019-03-02 14:28:402407瀏覽

這篇文章帶給大家的內容是關於COW機制已經相關類別的介紹,有一定的參考價值,有需要的朋友可以參考一下,希望對你有幫助。

COW機制已經相關類別

Vector和SynchronizedList

我們知道ArrayList是用來取代Vector的,Vector是執行緒安全的容器。因為它幾乎在每個方法聲明處都加了synchronized關鍵字來使容器安全。如果使用Collections.synchronizedList(new ArrayList())來使ArrayList變成是線程安全的話,也是幾乎都是每個方法都加上synchronized關鍵字的,只不過它不是加在方法的聲明處,而是方法的內部。

多執行緒下for迴圈迭代Vector或SynchronizedList,進行delete和get操作會發生陣列下標錯誤的例外。

在JDK5以後,Java推薦使用for-each(迭代器)來遍歷我們的集合,好處就是簡潔、陣列索引的邊界值只計算一次。如果使用for-each(迭代器)來做上面的操作,會拋出ConcurrentModificationException異常。

如果想要完美解決上面所講的問題,我們可以在遍歷前加鎖:

遍歷一下容器都要我加上鎖,這這不是要慢死了嗎。的確是挺慢的。因為加鎖粒度太大。

CopyOnWriteArrayList是同步List的替代品,CopyOnWriteArraySet是同步Set的替代品。

Hashtable、Vector加鎖的粒度大(直接在方法聲明處使用synchronized)ConcurrentHashMap、CopyOnWriteArrayList加鎖粒度小(用各種的方式來實現線程安全,例如我們知道的ConcurrentHashMap用了cascas 、volatile等方式來實現線程安全..)JUC下的線程安全容器在遍歷的時候不會拋出ConcurrentModificationException異常所以一般來說,我們都會使用JUC包下給我們提供的線程安全容器,而不是使用老一代的線程安全容器。

CopyOnWriteArrayList實作原理

CopyOnWriteArrayList是線程安全容器(相對於ArrayList),底層透過複製數組的方式來實現。 CopyOnWriteArrayList在遍歷的使用不會拋出ConcurrentModificationException異常,而且遍歷的時候就不用額外加鎖元素可以為null

/** 可重入锁对象 */
    final transient ReentrantLock lock = new ReentrantLock();
    /** CopyOnWriteArrayList底层由数组实现,volatile修饰 */
    private transient volatile Object[] array;

    final Object[] getArray() {
        return array;
    }
    final void setArray(Object[] a) {
        array = a;
    }
    // 初始化CopyOnWriteArrayList相当于初始化数组
    public CopyOnWriteArrayList() {
        setArray(new Object[0]);
    }

CopyOnWriteArrayList底層就是數組,加鎖就交由ReentrantLock來完成。

透過程式碼我們可以知道:在add(),set(),remove() 的時候就上鎖,並複製一個新數組,增加操作在新數組上完成,將array指向到新數組中,最後解鎖。在修改時,複製出一個新數組,修改的操作在新數組中完成,最後將新數組交由array變數指向。寫加鎖,讀不加鎖

CopyOnWriteArrayList缺點

內存佔用:如果CopyOnWriteArrayList經常要增刪改裡面的數據,經常要執行add()、set()、remove()的話,那是比較耗費記憶體的。

因為我們知道每次add()、set()、remove()這些增刪改操作都要複製一個陣列出來。

資料一致性:CopyOnWrite容器只能保證資料的最終一致性,無法保證資料的即時一致性。

從上面的例子也可以看出來,例如線程A在迭代CopyOnWriteArrayList容器的資料。線程B在線程A迭代的間隙中將CopyOnWriteArrayList部分的資料修改了(已經呼叫setArray()了)。但是線程A迭代出來的是原有的資料。

#

以上是COW機制已經相關類別的介紹的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:segmentfault.com。如有侵權,請聯絡admin@php.cn刪除