1. 程式人生 > 其它 >C#流總結(檔案流、記憶體流、網路流、BufferedStream、StreamReader/StreamWriter、TextReader/TextWriter)【轉】

C#流總結(檔案流、記憶體流、網路流、BufferedStream、StreamReader/StreamWriter、TextReader/TextWriter)【轉】

CopyOnWriteArraylist

CopyOnWrite容器

定義:寫時複製容器,當我們往一個容器新增元素的時候,不直接往當前容器新增,而是先將當前容器進行Copy,複製出一個新的容器,然後新的容器裡新增元素,新增完元素之後,再將原容器的引用指向新的容器。

1.CopyOnWriteArrayList的定義

CopyOnWriteArrayList 是jdk1.5以後併發包中提供的一種併發容器,寫操作通過建立底層陣列的新副本來實現,是一種讀寫分離的併發策略,我們也成為“寫時複製容器”,為了將讀取的效能發揮到極致,CopyOnWriteArrayList 讀取是完全不用加鎖的,並且更厲害的是:寫入也不會阻塞讀取操作。只有寫入和寫入之間需要進行同步等待。

2.為什麼使用CopyOnWriteArraylist

集合框架中的ArrayList 是非執行緒安全的,Vector雖然是執行緒安全的,但是處理方式簡單粗暴(synchronized),效能較差。而CopyOnWriteArrayList提供了不同的處理併發的思路。

3.什麼時候使用CopyOnWriteArraylist

很多時候,我們系統中處理的都是讀多寫少的併發場景。CopyOnWriterArrayList 允許併發的讀,讀操作是無鎖的,效能較高。寫操作的話,比如向容器增加一個元素,則首先將當前容器複製一份,然後在新副本上執行寫操作,結束之後再將原容器的引用指向新容器。

4.優點:

讀操作效能很高,因為無需任何同步措施,比較適用於讀多寫少的併發場景。Java的List在遍歷時,若中途有別的執行緒對List容器進行修改,則會丟擲ConcurrentModificationException異常。而CopyOnWriteArrayList由於其"讀寫分離"的思想,遍歷和修改操作分別作用在不同的List容器,所以在使用迭代器進行遍歷時候,也就不會丟擲ConcurrentModificationException異常了。

5.缺點:

1、記憶體佔用問題。因為CopyOnWrite的寫時複製機制,所以在進行寫操作的時候,記憶體裡會同時駐紮兩個物件的記憶體,舊的物件和新寫入的物件。

2、資料一致性問題。CopyOnWrite容器只能保證資料的最終一致性,不能保證資料的實時一致性。所以如果你希望寫入的的資料,馬上能讀到,請不要使用CopyOnWrite容器。當執行add或remove操作沒完成時,get獲取的仍然是舊陣列的元素

6.原始碼分析:

在使用CopyOnWriteArrayList之前,我們先閱讀其原始碼瞭解下它是如何實現的。以下程式碼是向CopyOnWriteArrayList中add方法的實現(向CopyOnWriteArrayList裡新增元素),可以發現在新增的時候是需要加鎖的,否則多執行緒寫的時候會Copy出N個副本出來。【以下原始碼基於jdk1.8】

    /**
     * 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();
            int len = elements.length;
            Object[] newElements = Arrays.copyOf(elements, len + 1);
            newElements[len] = e;
            setArray(newElements);
            return true;
        } finally {
            lock.unlock();
        }
    }
    /**
     * Removes the element at the specified position in this list.
     * Shifts any subsequent elements to the left (subtracts one from their
     * indices).  Returns the element that was removed from the list.
     *
     * @throws IndexOutOfBoundsException {@inheritDoc}
     */
    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();
        }
    }
    /**
     * Replaces the element at the specified position in this list with the
     * specified element.
     *
     * @throws IndexOutOfBoundsException {@inheritDoc}
     */
    public E set(int index, E element) {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            Object[] elements = getArray();
            E oldValue = get(elements, index);
            if (oldValue != element) {
                int len = elements.length;
                Object[] newElements = Arrays.copyOf(elements, len);
                newElements[index] = element;
                setArray(newElements);
            } else {
                // Not quite a no-op; ensures volatile write semantics
                setArray(elements);
            }
            return oldValue;
        } finally {
            lock.unlock();
        }
    }

參考文章:
https://www.jianshu.com/p/d1502f193e41
https://blog.csdn.net/Aplumage/article/details/117766260