每週讀源碼:源碼解讀fail-fast和fail-safe的實現機制

大家好,這裡是IT技術百貨,專注於有價值的IT技術知識分享;

今天跟大家分享集合遍歷中的fail-fast和fail-safe的實現機制

fail-fast和fail-safe指的是什麼

fail-fast和fail-safe指的是利用iterator進行集合遍歷時,當集合被修改之後是否拋出異常;

fail-fast機制會拋出異常(ConcurrentModificationException),而fail-safe機制不會拋出異常;

下面截圖中的代碼默認是fail-fast機制,運行的話會拋出異常:

每週讀源碼:源碼解讀fail-fast和fail-safe的實現機制

fail-fast機制拋出異常

fail-safe機制:


每週讀源碼:源碼解讀fail-fast和fail-safe的實現機制

failsafe機制 - 不會拋出異常


具體是怎麼實現的?

fail-fast機制:

使用fail-fast機制的集合在內部維護了一個字段:modCount ,用來記錄這個集合被修改了多少次,比如:增刪元素、替換元素、排序等

Iterator迭代器在初始化的時候,會記錄下這個 modCount 這個字段值,如下圖所示:

每週讀源碼:源碼解讀fail-fast和fail-safe的實現機制

初始化記錄modCount值

在遍歷過程中next、remove、add方法會對這個值進行校驗,具體代碼如下:

每週讀源碼:源碼解讀fail-fast和fail-safe的實現機制

校驗邏輯

特別說明:iterator內部的add和remove方法修改集合不會拋異常;iterator內部做了處理。

fail-safe機制:

fail-safe機制實現很簡單,就是將原來的集合copy一份,然後基於新拷貝的集合進行遍歷;

返回的Iterator實際上是COWIterator,通過源碼可以看出COWIterator持有對象的一份快照;


每週讀源碼:源碼解讀fail-fast和fail-safe的實現機制

快照源碼

之後所有的遍歷都是基於這個快照進行的;

靈魂拷問,真的是拷貝了一份新的嗎?

通過代碼來看,是直接將CopyOnWriteArrayList對象的元素數組賦值給了Iterator,這就說明本質上還是用的一個對象,那為什麼不會失敗呢?


每週讀源碼:源碼解讀fail-fast和fail-safe的實現機制

直接獲取CopyOnWriteArrayList對象的數組,並賦值給COWIterator


對比CopyOnWriteArrayList 和 ArrayList的源碼可以發現,CopyOnWriteArrayList的add和remvoe操作都是將原數組拷貝到一個新數組裡面,也就是不會改變原數組,而ArrayList事先聲明瞭一個大容量數組,當添加或者刪除操作時儘量在原數組上進行;


每週讀源碼:源碼解讀fail-fast和fail-safe的實現機制

CopyOnWriteArrayList的add操作


每週讀源碼:源碼解讀fail-fast和fail-safe的實現機制

CopyOnWriteArrayList的remove操作

每週讀源碼:String類的equals是怎麼實現的(阿里面試手寫代碼)

感謝瀏覽閱讀,如果覺得內容有價值歡迎點贊,收藏,轉發;喜歡請關注“IT技術百貨”


分享到:


相關文章: