簡體   English   中英

為什么即使使用鎖,也會出現ConcurrentModificationException?

[英]Why I get ConcurrentModificationException even though I am using locks?

這是我的課:

public class AComplicatedclass {
    private List<Connection> activeConnections;
    private Lock lock = new ReentrantLock();          

    public void printConnections() {
        lock.lock();
        for(Connection c : activeConnections){ //exception happens here
            ...prints details about connection
            activeConnections.remove(c);
        }
        lock.unlock();
    }

    private class MyThread extends TimerTask {

        public void run() {
            lock.lock();
                ...can alter activeConnections....
            lock.unlock();
        }

    }
}

如您所見,鎖對象應防止由於並發訪問該共享陣列而引起的問題。 然而,當printConnections()方法被調用時,我得到一個ConcurrentModificationExceptionfor

怎么會? 根本沒有並發修改!

您最有可能在for循環中修改您的集合。 作為有關ConcurrentModificationException狀態的文檔

例如,如果線程在使用快速失敗迭代器迭代集合時直接修改了集合,則迭代器將拋出此異常。

迭代器引發異常的原因是,無法再確定下一個要返回的元素。

所以,如果你想修改你的收藏,你需要或者切換到類似的CopyOnWriteArrayList或使用迭代器明確地作為

    Iterator<Connection> iterator = activeConenctions.iterator();
    while(iterator.hasNext()) {
        Connection c = iterator.next();
        if(/* what ever */) {
            iterator.remove();
        }
    }

即使您的應用程序是單線程的,在foreach迭代期間編輯列表幾乎總是會導致ConcurrentModificationException。

如果您需要在迭代過程中刪除項目,請使用迭代器:

final Iterator<Connection> iterator = activeConnections.iterator();
while(iterator.hasNext()) {
    final Connection connection = iterator.next();
    // ...prints details about connection
    iterator.remove();
}

根據ConcurrentModificationException的Javadoc:

例如,通常不允許一個線程修改Collection而另一個線程對其進行迭代。 通常,在這些情況下,迭代的結果是不確定的。 如果檢測到此行為,則某些Iterator實現(包括JRE提供的所有通用集合實現的實現)可能會選擇拋出此異常。 執行此操作的迭代器稱為快速失敗迭代器,因為它們會快速干凈地失敗,而不是在未來的不確定時間內冒任意,不確定的行為的風險。

這與不同步的訪問無關。

有問題的操作的一些示例:

  • 當前迭代的當前元素將從集合中刪除,在這種情況下,下一個元素是什么?
  • 已經迭代的某些元素將被刪除,然后在集合中稍后重新插入。 迭代器到達新位置時是否應該再次顯示它?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM