集合的modCount字段和Fail-Fast,F(xiàn)ail-Safe機制解釋

發(fā)現(xiàn)前面博客遺失了一篇ArrayList源碼解析的文章,這里就不打算重寫了,但是其中關(guān)于Fail-Fast機制的知識還是有必要記錄一下。

Fail-Fast機制

集合類數(shù)據(jù)類型都有一個迭代器用于遍歷集合,這樣的設(shè)計是為了能使用共同的方式迭代集合,而不依賴于集合的類型的具體實現(xiàn),比如無論哪種集合類型,都能使用foreach迭代。
但是在這個迭代過程中,我們需要防止通過原集合的提供的api對集合進行修改。因為這可能導致迭代結(jié)果不符合預期,或者是出現(xiàn)角標越界等問題。

  • 不符合預期的情況:在迭代過程中,往迭代的位置前插入元素,那么這個元素不會被迭代到。如果修改已經(jīng)迭代過的元素,那么迭代結(jié)果也和當前集合不一致。
  • 角標越界的情況:迭代過程中,刪除元素,迭代器游標可能超過了集合的長度。

所以在集合的基類中就定義了modCount字段,每當調(diào)用會對集合數(shù)據(jù)結(jié)構(gòu)產(chǎn)生變化的方法時,modCount++。
而迭代器中則定義了expectCount字段,在迭代器創(chuàng)建時,expectCount賦值為modCount,當?shù)鷷r出現(xiàn)expectCount不能與modCount時就會拋出ConcurrentModifiedException,這就是所謂的Fail-Fast機制:在迭代過程中可能出現(xiàn)錯誤的時候,提前拋出并發(fā)修改異常,中斷迭代操作。

當然,自己實現(xiàn)集合的子類也可以忽略這個字段,不需要Fail-Fast機制。在modCount字段中上面有這么一段文檔注釋:

If an implementation does not wish to provide fail-fast iterators, this field may be ignored.

容易誤解的地方

我看有篇博文說modCount是被volatile修飾的,然后這個小伙伴就將Fail-Fast機制和多線程一起巴拉巴拉的說了一堆……我翻完了jdk各個版本的源碼都沒發(fā)現(xiàn)這個修飾,估計是將transition誤以為volatile了。但其實即使是volatile也無法保證modCount線程安全,因為modCount++并不是一個原子性操作……

有的人覺得Fail-Fast機制和多線程有關(guān)、modCount是為了多線程設(shè)計的,這是很嚴重的錯誤的理解。
并不是多線程才會拋出并發(fā)修改異常的,而且這個機制也不是針對多線程設(shè)計的,modCount對多線程的意義不大,因為主線程中modCount++后,子線程讀取到的可能還是自增前的數(shù)值,所以多線程情況下反而可能不拋出ConcurrentModifiedException了,導致Fail-Fast機制失效。

Fail-Safe

在線程安全的集合中,迭代器是拷貝集合的副本進行迭代的,所以即使在迭代過程中修改原集合,也不會出現(xiàn)角標越界的情況。但相對的,會出現(xiàn)不符合預期的情況,此時迭代結(jié)果和原集合內(nèi)容已經(jīng)不一致。
所以這就是Fail-Safe命名的由來,安全的錯誤。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容