[英]ConcurrentModificationException with synchronized and unsynchronized methods
[英]ConcurrentModicationException due to unsynchronized synchronized methods
我有一堆从基类启动的Runnable对象。 这些对象在随机时间遍历并删除共享ArrayList中的项目。 我已经同步了这两种方法,但是却收到了ConcurrentModicationException
。 我相信这是因为它们是同步的,但彼此之间不同步 。 是这样吗 如果是这样,我应该获得哪个类的锁?
环境等级:
class Environment{
ArrayList<Critter> critter_array = new ArrayList<Critter>();
ArrayList<Food> food_array = new ArrayList<Food>();
Environment(){
Executor ex = Executors.newCachedThreadPool();
Critter A = new Critter();
Critter B = new Critter();
critter_array.add(A);
critter_array.add(B);
ex.execute(A);
ex.execute(B);
}
public synchronized void destroyFood(Food item){
Iterator<Food> iter = food_array.iterator();
while(iter.hasNext()){
Food temp = iter.next();
food_array.remove(temp);
break;
}
}
}
小动物班:
class Critter implements Runnable{
Environment envi;
Critter(Environment E){
envi = E;
}
@Override
public void run() {
//do other stuff
CritterUtilities.iteratorMethod(this, envi);
}
}
CritterUtilities类:
class CritterUtilities{
public static synchronized iteratorMethod(Critter self, Environment envi){
Iterator<OtherObject> iter = envi.getFood().listIterator();
while(iter.hasNext()){
Food temp = iter.next(); /////////Problem is here
//other stuff that's not related to the prob
}
}
}
堆栈跟踪:
Exception in thread "pool-1-thread-2" java.util.ConcurrentModificationException
at java.util.AbstractList$Itr.checkForComodification(Unknown Source)
at java.util.AbstractList$Itr.next(Unknown Source)
at CritterUtil.getViewableFood(CritterUtil.java:28)
at CritterUtil.getNearestFood(CritterUtil.java:41)
at Critter.hunt(Critter.java:163)
at Critter.run(Critter.java:139)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
该错误不一定在此处阻止多线程,而是在使用迭代器时从列表中删除项目的事实:
public synchronized void destroyFood(Food item){
Iterator<Food> iter = food_array.iterator();
while(iter.hasNext()){
Food temp = iter.next();
food_array.remove(temp); // <-- this is the problem
break;
}
}
而是使用Iterator.remove()
方法:
public synchronized void destroyFood(Food item){
Iterator<Food> iter = food_array.iterator();
while(iter.hasNext()){
iter.remove(); // <-- this is how you remove elements while iterating
break;
}
}
另一方面,您的同步是错误的。 您的每个synchronized
方法都在不同的对象上同步。 为了使它们都在同一个对象上同步,将它们全部同步在列表本身上可能是最简单的。
除了DaoWen发现的错误删除操作之外,同步也是错误的。 iteratorMethod()
和destroyFood()
不会使用相同的对象进行同步。 当前,他们使用各自的对象进行同步。 应该是这样的:
public void destroyFood(Food item) {
synchronized (food_array) {
// ... proceed with the removal
}
}
和
public static iteratorMethod(Critter self, Environment envi){
List<OtherObject> list = envi.getFood();
synchronized (list) {
// the rest of iteratorMethod should go here
}
}
(我假设getFood()返回food数组,因此对象将相同)。
相同的解决方案应应用于修改或迭代食物清单的任何其他方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.