1. 程式人生 > >快速失敗與安全失敗

快速失敗與安全失敗

一、快速失敗(fail-fast)
(是什麼?)
在用迭代器遍歷一個集合物件時,如果遍歷過程中對集合物件的內容進行了修改(增加、刪除、修改),則會丟擲Concurrent Modification Exception。

(原理)
在這裡插入圖片描述 在這裡插入圖片描述
在呼叫 next() 和 remove()時,都會執行 checkForComodification()。
若 modCount 不等於 expectedModCount,
則丟擲ConcurrentModificationException異常,產生fail-fast事件。
無論是add()、remove(),還是clear(),只要涉及到修改集合中的元素個數時,都會改變modCount的值。

(解決方案)
使用iterator操作將ArrayList替換成java.util.concurrent包下對應的類。

二、安全失敗(fail-safe)
(是什麼?)
採用安全失敗機制的集合容器,在遍歷時不是直接在集合內容上訪問的,而是先複製原有集合內容,在拷貝的集合上進行遍歷。

(原理)
在這裡插入圖片描述
所用到的併發容器:CopyOnWrite容器

1.CopyOnWrite容器即寫時複製的容器。
2.以新增為例:通俗的理解是當我容器新增元素的時候,不直接往當前容器新增,而是先將當前容器進行Copy,複製出一個新的容器,然後新的容器裡新增們往一個元素,新增完元素之後,再將原容器的引用指向新的容器。
3.以新增為例,這樣做的好處是我們可以對CopyOnWrite容器進行併發的讀,而不需要加鎖,因為當前容器不會新增任何元素。所以CopyOnWrite容器也是一種讀寫分離的思想,讀和寫不同的容器。

三、快速失敗與安全失敗的實現原理區別
在這裡插入圖片描述

四、使用場景
1.java.util包下的集合類都是快速失敗的,不能在多執行緒下發生併發修改(迭代過程中被修改),迭代器的快速失敗行為應該僅用於檢測程式錯誤。
2.java.util.concurrent包下的容器都是安全失敗,可以在多執行緒下併發使用,併發修改。
3.CopyOnWriteArrayList中寫操作需要大面積複製陣列,所以效能肯定很差,但是讀操作因為操作的物件和寫操作不是同一個物件,讀之間也不需要加鎖,讀和寫之間的同步處理只是在寫完後通過一個簡單的“=”將引用指向新的陣列物件上來,這個幾乎不需要時間,這樣讀操作就很快很安全,適合在多執行緒裡使用,絕對不會發生ConcurrentModificationException,所以最後得出結論:CopyOnWriteArrayList適合使用在讀操作遠遠大於寫操作的場景裡,比如快取。