/**
* The number of times this HashMap has been structurally modified
* Structural modifications are those that change the number of mappings in
* the HashMap or otherwise modify its internal structure (e.g.,
* rehash). This field is used to make iterators on Collection-views of
* the HashMap fail-fast. (See ConcurrentModificationException).
*/
transient int modCount;
在ArrayList,LinkedList,HashMap等等的內部實現增,刪,改中我們總能看到modCount的身影,modCount字面意思就是修改次數,但為什么要記錄modCount的修改次數呢?
大家發現一個公共特點沒有,所有使用modCount屬性的全是線程不安全的,這是為什么呢?說明這個玩意肯定和線程安全有關系嘍,那有什么關系呢?
在一個迭代器初始的時候會賦予它調用這個迭代器的對象的mCount,如何在迭代器遍歷的過程中,一旦發現這個對象的modcount和迭代器中存儲的modcount不一樣那就拋異常,每次調用對象的next()方法的時候都會調用checkForComodification()方法進行一次檢驗,checkForComodification()方法中做的工作就是比較expectedModCount 和modCount的值是否相等,如果不相等,就認為還有其他對象正在對當前的List進行操作,那個就會拋出ConcurrentModificationException異常。
Fail-Fast機制
我們知道java.util.HashMap不是線程安全的,因此如果在使用迭代器的過程中有其他線程修改了map,那么將拋出ConcurrentModificationException,這就是所謂fail-fast策略。這一策略在源碼中的實現是通過 modCount 域,modCount 顧名思義就是修改次數,對HashMap內容的修改都將增加這個值,那么在迭代器初始化過程中會將這個值賦給迭代器的expectedModCount。在迭代過程中,判斷 modCount 跟 expectedModCount 是否相等,如果不相等就表示已經有其他線程修改了 Map:注意到 modCount 聲明為 volatile,保證線程之間修改的可見性。