寫時複製技術的實現與介紹(Copy-On-Write)

Copy-On-Write

1,什麼是寫時複製(Copy-On-Write)容器?

寫時複製是指:在併發訪問的情景下,當需要修改JAVA中Containers的元素時,不直接修改該容器,而是先複製一份副本,在副本上進行修改。修改完成之後,將指向原來容器的引用指向新的容器(副本容器)。

2,寫時複製帶來的影響

①由於不會修改原始容器,只修改副本容器(JMM原理)。因此,可以對原始容器進行併發地讀。其次,實現了讀操作與寫操作的分離,讀操作發生在原始容器上,寫操作發生在副本容器上。
②數據一致性問題:讀操作的線程可能不會立即讀取到新修改的數據,因爲修改操作發生在副本上。但最終修改操作會完成並更新容器,因此這是最終一致性。

3,應用場景

CopyOnWrite容器適用於讀多寫少的場景。因爲寫操作時,需要複製一個容器,造成內存開銷很大,也需要根據實際應用把握初始容器的大小。
不適合於數據的強一致性場合。若要求數據修改之後立即能被讀到,則不能用寫時複製技術。因爲它是最終一致性。
總結:寫時複製技術是一種很好的提高併發性的手段。

4,爲什麼會出現COW?

集合類(ArrayList、HashMap)上的常用操作是:向集合中添加元素、刪除元素、遍歷集合中的元素然後進行某種操作。當多個線程併發地對一個集合對象執行這些操作時就會引發ConcurrentModificationException,比如線程A在for-each中遍歷ArrayList,而線程B同時又在刪除ArrayList中的元素,就可能會拋出ConcurrentModificationException,可以在線程A遍歷ArrayList時加鎖,但由於遍歷操作是一種常見的操作,加鎖之後會影響程序的性能,因此for-each遍歷選擇了不對ArrayList加鎖而是當有多個線程修改ArrayList時拋出ConcurrentModificationException,因此,這是一種設計上的權衡。
爲了應對多線程併發修改這種情況,一種策略就是本文的主題“寫時複製”機制;另一種策略是:線程安全的容器類:
ArrayList—>CopyOnWriteArrayList
HashSet—>CopyOnWriteHashSet
HashMap—>ConcurrentHashMap
而ConcurrentHashMap並不是從“複製”這個角度來應對多線程併發修改,而是引入了分段鎖(JDK7);CAS解決多線程併發修改的問題。

個人意見相互學習,若有不同請共同討論!

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