Java-synchronized ArrayList仍然是ConcurrentModificationException

Java-synchronized ArrayList仍然是ConcurrentModificationException,java,arraylist,synchronized,Java,Arraylist,Synchronized,我得到了一个final ArrayList routingTable=new ArrayList()可多次访问。 但我只在一个点上得到一个ConcurrentModificationException,它位于以下线程中: Thread checkReplies = new Thread(() -> { while (true) { synchronized (routingTable) { for (RoutingTableEntry

我得到了一个
final ArrayList routingTable=new ArrayList()可多次访问。
但我只在一个点上得到一个
ConcurrentModificationException
,它位于以下线程中:

Thread checkReplies = new Thread(() -> {

    while (true) {

        synchronized (routingTable) {

            for (RoutingTableEntry entry : routingTable) { // throws it here

                // do smth
            }
        }

        // [...]
    }
 });
 checkReplies.start();
即使
routingTable
已经同步,它也会在循环中抛出异常。每个类只执行一次此线程


有什么想法吗?

有两种可能性:

  • 类中有修改路由表的其他代码,执行此操作时不使用
    同步(路由表)
    。因此,当其他代码在迭代过程中修改列表时,您会得到错误

  • 您正在修改注释为“do smth”的列表。仅仅因为您已经同步了列表,这并不意味着您可以在循环使用其迭代器时对其进行修改。您不能(除了通过迭代器本身,这意味着您不能使用增强的
    for
    循环)。(有时,由于
    ArrayList
    实现的细节,您可以侥幸逃脱,但有时则无法逃脱。)

  • 下面是#2()的一个示例:


    (还有
    add
    set
    操作。)

    ConcurrentModificationException
    在线程化的意义上不一定是“并发的”,它可以是“并发的”,即在迭代集合的同时不应直接修改集合

    很长一段时间以来,它也存在于文档中(摘自Java7:)

    请注意,此异常并不总是表示对象已被其他线程并发修改。如果单个线程发出一系列违反对象约定的方法调用,该对象可能会引发此异常例如,如果线程在使用fail fast迭代器迭代集合时直接修改集合,迭代器将抛出此异常。


    for(x:y)
    使用了一个迭代器,它很容易成为一个“快速失败”迭代器。

    从您在原始问题中的评论开始,您在进行迭代时正在删除
    路由表中的项目

    无法执行此操作(如果
    路由表已同步,也可以执行此操作)


    您是否在<代码>周期的<代码>中添加/删除<代码>路由表<代码>中的项目?是否有特殊原因使您不使用<代码>集合。synchronizedList()
    CopyOnWriteArrayList
    ?@Joe迭代
    集合。synchronizedList
    与迭代同步块中的列表不同。@GabrieleMariotti我调用一个方法,该方法将删除(我是否应该使该方法同步?@Stefanxyz这就是问题所在。你做不到。我不太清楚你说“你做不到(除了…)”是什么意思。您是否忘记完成句子,或者您不能更改synchronized语句中列表的任何内容?@Stefanxyz-句子已完成,有一些修改方法可以在迭代过程中安全使用。但是,要使用它们,您必须显式地使用
    listIterator
    和标准
    for
    或类似的循环,您不能使用增强的
    for
    循环(因为它对您隐藏了迭代器)。另请参阅我对答案的补充:您将两件基本上不相关的事情(同步和并发修改)混为一谈。谢谢您的回答。多亏了加布里埃尔·马里奥蒂和特维马达尔,我已经意识到了这一点。我将该结构修改为一个正常的“for”循环,这使得它成为可能(通过列表更改减少索引),感谢我实际上认为它是并发的(@tevemadar提到了它),现在它变得有意义了。
    var routingTable = new ArrayList<String>();
    routingTable.add("one");
    routingTable.add("two");
    routingTable.add("three");
    synchronized (routingTable) {
        for (String entry : routingTable) {
            if (entry.equals("two")) {
                routingTable.add("four");
            }
        }
    }
    
    for (var it = routingTable.listIterator(); it.hasNext; ) {
        var entry = it.next();
        if (/*...some condition...*/) {
            it.remove(); // Removes the current entry
        }
    }
    
    for (RoutingTableEntry entry : routingTable) { // throws it here
         // routingTable.remove(....);
    }