CopyOnWriteArrayList源碼解析

  • 依據jdk1.8源碼分析

新建

  • 創建一個零長度數組
private transient volatile Object[] array;//底層數據

添加數據

  • 先上同步鎖
  • 對原始數組進行拷貝(淺拷貝),然後在拷貝後的數組上進行修改
  • 將修改後的結果賦值給array
public boolean add(E e) {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            Object[] elements = getArray();
            int len = elements.length;
            Object[] newElements = Arrays.copyOf(elements, len + 1);
            newElements[len] = e;
            setArray(newElements);
            return true;
        } finally {
            lock.unlock();
        }
    }

獲取數據

  • 獲取的時候沒有加鎖(由於array是volatile,所以會先從主內存更新數據,所以線程中的數據應該始終都是最新的)

刪除數據

  • 先上同步鎖
  • 對原始數據進行拷貝,在拷貝的時候不拷貝那個需要刪除的數據
  • 將修改後的結果賦值給array
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)
                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();
        }
    }

遍歷數據

  • 使用listIterator()獲取迭代器
  • listIterator()中將array賦給COWIterator(實現了ListIterator)。這裏沒有進行復制
  • 可以調用hasNext() hasPrevious() next() previous()
  • 注意:set() add() remove()都會直接拋出異常UnsupportedOperationException

總結

  • 由於每次刪除和增加元素都會拷貝一個新的數組出來,因此原本數組中的元素已經過時。所以即使這個時候另一個線程修改數據,也不會報錯,只是數據不是最新的
  • 增刪改上鎖、讀不上鎖
  • 由於每一次修改都會有新的數組,array使用volatile修飾,所以在讀的時候能確保使用的到的是最新的數組副本(多線程的情況下始終都是在主內存中讀取)

參考jdk1.8源碼
https://www.cnblogs.com/java-zhao/p/5121944.html

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