亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

迭代器應該在源修改后什么時候拋出異常?

迭代器應該在源修改后什么時候拋出異常?

白豬掌柜的 2023-01-05 16:48:01
在下面的代碼片段中,為 ArrayList 創建了一個迭代器,之后 ArrayList 的結構發生了變化。然后使用迭代器。ArrayList<Integer> list = new ArrayList<>(2);list.add(1);Iterator<Integer> itr = list.iterator();list.clear();list.add(2);list.add(3);while (itr.hasNext()) {    System.out.println(itr.next());}正如預期的那樣, aConcurrentModificationException被拋出itr.next()?,F在,看看這個:ArrayList<Integer> list = new ArrayList<>(2);list.add(1);int modCount = 1;Iterator<Integer> itr = list.iterator();do {    list.clear();    list.add(2);    list.add(3);    modCount += 3;} while (modCount != 1);while (itr.hasNext()) {    System.out.println(itr.next());}幾秒后,執行結束,沒有任何異常,結果為:23ArrayList 在結構上發生了變化,它的最終狀態與第一個代碼片段相同,但仍然沒有拋出異常,即使在第一個代碼片段中它拋出了異常。查看 ArrayList 源代碼后,這是意料之中的,因為底層 modCount 是 int 類型。對 ArrayList 進行足夠的修改會導致 modCount 溢出,在某個時候返回 1。Iterator 認為 ArrayList 沒有改變,因此不會拋出異常。在 Java SE 12 文檔中,對于 ArrayList 類,聲明如下:請注意,無法保證迭代器的快速失敗行為,因為一般來說,在存在非同步并發修改的情況下不可能做出任何硬性保證。很明顯,迭代器可能會犯“錯誤”,但這又是針對非同步并發修改的,對吧?但是,上面的第二個片段是同步的。這里發生了什么?第二個片段中的 Iterator 應該是這樣的嗎?如果是這樣,那么 long 類型的 modCount 會不會好一點(問題仍然不會消失,但是 2^64 + 1 修改在合理的時間內執行是不可行的)。這也可以在其他Collections 中觀察到,它們使用相同的 int modCount 機制。
查看完整描述

3 回答

?
縹緲止盈

TA貢獻2041條經驗 獲得超4個贊

Javadoc的下一句話:

Fail-fast 迭代器ConcurrentModificationException在盡力而為的基礎上拋出。因此,編寫依賴于此異常的正確性的程序是錯誤的:迭代器的快速失敗行為應該僅用于檢測錯誤。

您只是很幸運(或者更確切地說,您正在構建一個非常精確的情況)您的代碼不會拋出 CME。

我不會過多解讀前一句關于“非同步并發修改”的強調。對此的一種迂腐的解讀是,因為一件事可能發生,而這打破了保證,整個保證就被打破了,所以保證可能被打破的其他方式并不重要。


查看完整回答
反對 回復 2023-01-05
?
ITMISS

TA貢獻1871條經驗 獲得超8個贊

您所做的一切都是創建一個場景,在該場景中,modCount 最終會環繞,直到它處于某種狀態以反映沒有發生修改,因此沒有 CME。也許您希望 modCount 是 long 而不是 int。



查看完整回答
反對 回復 2023-01-05
?
瀟湘沐

TA貢獻1816條經驗 獲得超6個贊

稍加思索后,我得出結論:

  1. 如果 Iterator 拋出 a ConcurrentModificationException,則源在正在進行的迭代中進行了結構修改。

  2. 如果源在其迭代器處于正在進行的迭代中時在結構上被修改,則該迭代器可能會可能不會拋出ConcurrentModificationException.

考慮到這一點,迭代器嘗試拋出 a 的唯一原因ConcurrentModificationException是幫助調試。總比沒有好,尤其是在一般情況下。

在 modCount 中使用 long 而不是 int 將增加 may 的機會減少may not在 2 中的機會。但只有使用可以容納無限位數的類型才能使may有機會 1.0 和may沒有0.0 的機會(當然至少在那種架構下)。因此,無論 modCount 使用多少個有限位,它都不會漸近地產生影響。


查看完整回答
反對 回復 2023-01-05
  • 3 回答
  • 0 關注
  • 169 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號