【问题标题】:ConcurrentModificationException thrown in a multithreaded program [duplicate]在多线程程序中抛出 ConcurrentModificationException [重复]
【发布时间】:2016-01-30 22:37:37
【问题描述】:

我正在尝试模拟一个程序,该程序模拟不同线程在 ArrayList 中删除和添加对象。但是,在模拟的后期,我得到了 concurrentModificationExceptions(当线程试图访问和修改同一个变量,而迭代器被用来遍历数据时)。我已经对其进行了搜索,并看到了一些关于此的主题,即我需要使用锁/同步和/或使用 ListIterators 而不是增强的 for 循环,但是,这些选项似乎都不能解决问题。到目前为止,这是我尝试做的事情:

public Object removeSomething1(){
    synchronized(this){ //Also tried only putting it around the remove block
        for(Object o : myList){
            myList.remove(o);
            return o;
        }
    }

}

//This is another variaton which did not yield any improved result

public Object removeSomething2(){
    ListIterator<Object> iter = myList.listIterator();
        While(iter.hasNext()){
            Object s = iter.next();
            synchronized(this){
                iter.remove();

            }
            return s;

        }

    }

//After some request here is also the simple code which adds to the list

public addSomething(Object o){
    myList.add(o);
}

我执行了 5 个线程,它们在它们的 run() 方法中以 500 毫秒的间隔调用这些方法(使用 Thread.sleep())。如果我增加每个线程中的睡眠计时器并在每个线程实例之间放置一个 Thread.sleep() ,问题似乎就消失了,但我希望线程(接近)同时运行而不会干扰迭代器同时引发 ConcurrentModificationException。

【问题讨论】:

  • 为什么不用for (Object o : myList) myList.remove(o); 而不是myList.removeAll()
  • 因为我不想删除所有对象。我希望每个线程都删除自己的对象。这只是一个更大、更实质的程序的示例代码,其中每个线程添加并随后删除它添加的对象,但如上所述,异常仅在代码的“删除部分”中引发。
  • @tomSurge 你能显示所有修改列表的代码吗?什么添加到列表中以及如何添加?顺便说一句,您发布的内容甚至没有编译。
  • 请不要发布我可以看到不会编译的代码并告诉我它可以编译。如果将那里的内容复制到源文件中,则无法编译,因为并非通过该方法的每条路径都会导致 return 语句。
  • 一般来说,您需要移动synchronized 块以包含所有removeSomething2()。您必须同步整个迭代。

标签: java multithreading loops synchronization locking


【解决方案1】:

根据用户 Louis Wasserman 的建议,我移动了 synchronized 块以包含所有 removeSomething2()。这是有道理的,因为现在只让一个线程一次完成整个迭代。解决方案如下所示:

public Object removeSomething2(){
synchronized(this){
    ListIterator<Object> iter = myList.listIterator();
        While(iter.hasNext()){
            Object s = iter.next();
            iter.remove();
            return s;
        }
    }
}

【讨论】:

  • 所有代码都相当于myList.remove(0);... 而不是将整个方法主体放在this 的同步块中,您可以使方法同步... 最后,它是不是您所描述的问题的解决方案,如果您在多个线程的列表中添加和删除项目,而您添加的内容仍未同步...
  • 还有,还是肯定不会编译。
猜你喜欢
  • 2017-02-10
  • 1970-01-01
  • 2019-03-12
  • 2020-02-21
  • 2013-02-12
  • 1970-01-01
  • 2016-06-20
  • 2011-08-29
相关资源
最近更新 更多