今天,我們來談談fail-fast與fail-safe是什么以及工作機制


今天,我們來談談fail-fast與fail-safe是什么以及工作機制

fail-fast是什么?

fail-fast的字面意思是“快速失敗”。當我們在遍歷集合元素的時候,經常會使用迭代器,但在迭代器遍歷元素的過程中,如果集合的結構被改變的話,就會拋出異常,防止繼續遍歷。這就是所謂的快速失敗機制。

下面我們來看看官方文檔在HashMap這個集合中,它是怎么解釋fail-fast的(如下圖):

 

意思就是說,當Iterator這個迭代器被創建后,除了迭代器本身的方法(remove)可以改變集合的結構外,其他的因素如若改變了集合的結構,都被拋出ConcurrentModificationException異常。

請在繼續看官方的描述:

 

 

意思就是說:迭代器的快速失敗行為是不一定能夠得到保證的,一般來說,存在非同步的並發修改時,不可能做出任何堅決的保證的。但是快速失敗迭代器會做出最大的努力來拋出ConcurrentModificationException。因此,編寫依賴於此異常的程序的做法是不正確的。正確的做法應該是:迭代器的快速失敗行為應該僅用於檢測程序中的bug.

稍微總結下:fail-fast,即快速失敗機制,它是java集合中的一種錯誤檢測機制,當多個線程(當個線程也是可以滴),在結構上對集合進行改變時,就有可能會產生fail-fast機制。

這里,我解釋下什么是結構上的改變。 例如集合上的插入和刪除就是結構上的改變,但是,如果是對集合中某個元素進行修改的話,並不是結構上的改變哦。

下面,我們來演示下在單線程的環境下,fail-fast拋出異常的實例:

		for(int i = 10; i < 100; i++){
		map.put(i, i);
	}
	List<Integer> list = new ArrayList<>();
	for(int i = 0; i < 20; i++){
		list.add(i);
	}
	Iterator<Integer> it = list.iterator();
	int temp = 0;
	while(it.hasNext()){
		if(temp == 3){
			temp++;
			list.remove(3);
		}else{
			temp++;
			System.out.println(it.next());
		}
	}
}

  

打印結果:

 

 

**結果分析:**因為當temp==3的時候,執行list.remove()方法,集合的結構被改變了,所以再次遍歷迭代器的時候,就會拋出異常。


fail-fast的工作原理

我們首先先來看下源碼

 

**分析:**從源碼我們可以發現,迭代器在執行next()等方法的時候,都會調用checkForComodification()這個方法,查看modCount==expectedModCount?如果相等則拋出異常。

expectedModcount:這個值在對象被創建的時候就被賦予了一個固定的值modCount。也就是說這個值是不變的。也就是說,如果在迭代器遍歷元素的時候,如果modCount這個值發生了改變,那么再次遍歷時就會拋出異常。
什么時候modCount會發生改變呢?

這次就不帶大家看源碼了。其實當我們對集合的元素的個數做出改變的時候,modCount的值就會被改變,如果刪除,插入。但修改則不會。


fail-fast的一些處理方法

如果我們不希望在迭代器遍歷的時候因為並發等原因,導致集合的結構被改變,進而可能拋出異常的話,我們可以在涉及到會影響到modCount值改變的地方,加上同步鎖(synchronized),或者直接使用 Collections.synchronizedList來解決。


fail-fast就先講到這里,下面簡單講講fail-safe與fail-fast的區別

當我們對集合結構上做出改變的時候,fail-fast機制就會拋出異常。但是,對於采用fail-safe機制來說,就不會拋出異常(大家估計看到safe兩個字就知道了)。

這是因為,當集合的結構被改變的時候,fail-safe機制會在復制原集合的一份數據出來,然后在復制的那份數據遍歷。

因此,雖然fail-safe不會拋出異常,但存在以下缺點:

  1. 復制時需要額外的空間和時間上的開銷。

  2. 不能保證遍歷的是最新內容。

如果你習慣在微信公眾號看技術文章
想要獲取更多資源的同學
歡迎關注我的公眾號:苦逼的碼農
每天向你推送 各種視頻資源,電子書、 技術文章以及
和面試有關的 算法專題 每日一題

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM