JDK并發(fā)工具類源碼--CopyOnWriteArrayList

1.簡介

CopyOnWriteArrayList是一個并發(fā)容器,它是一個線程安全且讀操作無鎖的ArrayList,寫操作則通過創(chuàng)建底層的副本來實現(xiàn),可以理解為一種讀寫分離的并發(fā)策略。
在多數(shù)情況下,我們的系統(tǒng)一般都是面對讀多寫少的并發(fā)情景。CopyOnWriteArrayList容器允許并發(fā)讀,讀操作是無鎖的,性能較高。對于寫操作,當(dāng)向容器添加一個元素時,首先需要將當(dāng)前容器復(fù)制一份,然后在副本上進行添加操作,之后在將原引用指向新容器。

2.方法

2.1 add

public boolean add(E e) {
        //ReentrantLock加鎖,保證線程安全
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            Object[] elements = getArray();
            int len = elements.length;
            //拷貝原容器,長度為原容器長度加一
            Object[] newElements = Arrays.copyOf(elements, len + 1);
            //在新副本上執(zhí)行添加操作
            newElements[len] = e;
            //將原容器引用指向新副本
            setArray(newElements);
            return true;
        } finally {
            //解鎖
            lock.unlock();
        }
    }

添加的邏輯是先將原容器copy一份,然后在新副本上執(zhí)行寫操作,之后再切換引用,這個過程是要加鎖的。

2.2 remove

 public E remove(int index) {
        //加鎖
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            Object[] elements = getArray();
            int len = elements.length;
            E oldValue = get(elements, index);
            int numMoved = len - index - 1;
            if (numMoved == 0)
                //如果要刪除的是列表末端數(shù)據(jù),拷貝前l(fā)en-1個數(shù)據(jù)到新副本上,再切換引用
                setArray(Arrays.copyOf(elements, len - 1));
            else {
                //否則,將除要刪除元素之外的其他元素拷貝到新副本中,并切換引用
                Object[] newElements = new Object[len - 1];
                System.arraycopy(elements, 0, newElements, 0, index);
                System.arraycopy(elements, index + 1, newElements, index,
                                 numMoved);
                setArray(newElements);
            }
            return oldValue;
        } finally {
            //解鎖
            lock.unlock();
        }
    }

刪除操作將要刪除元素之外的其他元素拷貝到新副本中,然后在切換引用,將原容器應(yīng)用指向新副本。

2.3 get

public E get(int index) {
        return get(getArray(), index);
    }

CopyOnWriteArrayList的讀操作是不用加鎖的,性能很高。

3.總結(jié)

1.讀操作的性能非常高,比較適用于讀多寫少的并發(fā)場景。
2.內(nèi)存占用問題,每次進行寫操作時,都要講原容器拷貝一份,如果數(shù)據(jù)量大時,對內(nèi)存的壓力非常大。
3.無法保證實時性,不能滿足強一致性,CopyOnWriteArrayList由于策略的原因,寫和讀分別作用在新老不同的容器上。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容