java中fail-fast 和 fail-safe的區別

來源:互聯網
上載者:User

標籤:out   派生   source   pop   last   static   遍曆   rem   strong   

原文地址:http://javahungry.blogspot.com/2014/04/fail-fast-iterator-vs-fail-safe-iterator-difference-with-example-in-Java.html

在我們詳細討論這兩種機制的區別之前,首先得先瞭解並發修改。

1.什麼是同步修改?

當一個或多個線程正在遍曆一個集合Collection,此時另一個線程修改了這個集合的內容(添加,刪除或者修改)。這就是並發修改

2.什麼是 fail-fast 機制?

fail-fast機制在遍曆一個集合時,當集合結構被修改,會拋出Concurrent Modification Exception。

fail-fast會在以下兩種情況下拋出ConcurrentModificationException

(1)單線程環境

集合被建立後,在遍曆它的過程中修改了結構。

注意 remove()方法會讓expectModcount和modcount 相等,所以是不會拋出這個異常。

(2)多線程環境

當一個線程在遍曆這個集合,而另一個線程對這個集合的結構進行了修改。

 

注意,迭代器的快速失敗行為無法得到保證,因為一般來說,不可能對是否出現不同步並發修改做出任何硬性保證。快速失敗迭代器會盡最大努力拋出 ConcurrentModificationException。因此,為提高這類迭代器的正確性而編寫一個依賴於此異常的程式是錯誤的做法:迭代器的快速失敗行為應該僅用於檢測 bug。

3. fail-fast機制是如何檢測的?

迭代器在遍曆過程中是直接存取內部資料的,因此內部的資料在遍曆的過程中無法被修改。為了保證不被修改,迭代器內部維護了一個標記 “mode” ,當集合結構改變(添加刪除或者修改),標記"mode"會被修改,而迭代器每次的hasNext()和next()方法都會檢查該"mode"是否被改變,當檢測到被修改時,拋出Concurrent Modification Exception

。下面看看ArrayList迭代器部分的源碼

 

[java] view plain copy  
  1. private class Itr implements Iterator<E> {  
  2.         int cursor;  
  3.         int lastRet = -1;  
  4.         int expectedModCount = ArrayList.this.modCount;  
  5.   
  6.         public boolean hasNext() {  
  7.             return (this.cursor != ArrayList.this.size);  
  8.         }  
  9.   
  10.         public E next() {  
  11.             checkForComodification();  
  12.             /** 省略此處代碼 */  
  13.         }  
  14.   
  15.         public void remove() {  
  16.             if (this.lastRet < 0)  
  17.                 throw new IllegalStateException();  
  18.             checkForComodification();  
  19.             /** 省略此處代碼 */  
  20.         }  
  21.   
  22.         final void checkForComodification() {  
  23.             if (ArrayList.this.modCount == this.expectedModCount)  
  24.                 return;  
  25.             throw new ConcurrentModificationException();  
  26.         }  
  27.     }  


可以看到它的標記“mode”為 expectedModeCount

 

 

4. fail-safe機制

fail-safe任何對集合結構的修改都會在一個複製的集合上進行修改,因此不會拋出ConcurrentModificationException

fail-safe機制有兩個問題

(1)需要複製集合,產生大量的無效對象,開銷大

(2)無法保證讀取的資料是目前未經處理資料結構中的資料。

 

5 fail-fast 和 fail-safe的例子

 

[java] view plain copy  
  1. import java.util.HashMap;  
  2. import java.util.Iterator;  
  3. import java.util.Map;  
  4.   
  5. public class FailFastExample  
  6. {  
  7.       
  8.       
  9.     public static void main(String[] args)  
  10.     {  
  11.         Map<String,String> premiumPhone = new HashMap<String,String>();  
  12.         premiumPhone.put("Apple", "iPhone");  
  13.         premiumPhone.put("HTC", "HTC one");  
  14.         premiumPhone.put("Samsung","S5");  
  15.           
  16.         Iterator iterator = premiumPhone.keySet().iterator();  
  17.           
  18.         while (iterator.hasNext())  
  19.         {  
  20.             System.out.println(premiumPhone.get(iterator.next()));  
  21.             premiumPhone.put("Sony", "Xperia Z");  
  22.         }  
  23.           
  24.     }  
  25.       
  26. }  


輸出

 

 

iPhone 
Exception in thread "main" java.util.ConcurrentModificationException        at java.util.HashMap$HashIterator.nextEntry(Unknown Source)        at java.util.HashMap$KeyIterator.next(Unknown Source)        at FailFastExample.main(FailFastExample.java:20)

 

 

 

[java] view plain copy  
  1. import java.util.concurrent.ConcurrentHashMap;  
  2. import java.util.Iterator;  
  3.   
  4.   
  5. public class FailSafeExample  
  6. {  
  7.       
  8.       
  9.     public static void main(String[] args)  
  10.     {  
  11.         ConcurrentHashMap<String,String> premiumPhone =   
  12.                                new ConcurrentHashMap<String,String>();  
  13.         premiumPhone.put("Apple", "iPhone");  
  14.         premiumPhone.put("HTC", "HTC one");  
  15.         premiumPhone.put("Samsung","S5");  
  16.           
  17.         Iterator iterator = premiumPhone.keySet().iterator();  
  18.           
  19.         while (iterator.hasNext())  
  20.         {  
  21.             System.out.println(premiumPhone.get(iterator.next()));  
  22.             premiumPhone.put("Sony", "Xperia Z");  
  23.         }  
  24.           
  25.     }  
  26.       
  27. }  


輸出

 

 

S5HTC oneiPhone

 

 

6. fail-fast和 fail-safe 的區別



  Fail Fast Iterator Fail Safe Iterator
Throw ConcurrentModification Exception Yes No
Clone object No Yes
Memory Overhead No Yes
Examples HashMap,Vector,ArrayList,HashSet
CopyOnWriteArrayList,
ConcurrentHashMap

java中fail-fast 和 fail-safe的區別

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.