ConcurrentModificationException,尽pipe使用同步

public synchronized X getAnotherX(){ if(iterator.hasNext()){ X b = iterator.next(); String name = b.getInputFileName(); ... return b; } else{return null;} } 

尽pipe在声明头文件中有synchronized语句,但是我仍然在我使用iterator.next()的那一行得到一个ConcurrentModificationExceptionexception。 这里怎么了?

ConcurrentModificationException通常与多个线程无关。 大多数情况下,这是因为您正在修改迭代循环体内迭代的集合。 例如, 这将导致它:

 Iterator iterator = collection.iterator(); while (iterator.hasNext()) { Item item = (Item) iterator.next(); if (item.satisfiesCondition()) { collection.remove(item); } } 

在这种情况下,您必须改用iterator.remove()方法。 如果您要添加到集合中,则会发生同样的情况,在这种情况下,没有常规解决scheme。 但是,如果处理一个列表并且具有add()方法,则可以使用子typesListIterator

我同意上面有关ConcurrentModificationException的声明,这经常是由于在迭代中修改同一线程中的集合而导致的。 但是,并不总是这个原因。

关于synchronized的事情要记住,只有当访问共享资源的每个人都synchronized ,它才保证独占访问。

例如,您可以同步访问共享variables:

 synchronized (foo) { foo.setBar(); } 

而且你可以认为你有独占访问权限。 但是,没有什么可以阻止另一个线程在没有synchronized块的情况下执行某些操作:

 foo.setBar(); // No synchronization first. 

通过运气不好(或墨菲定律 ,“任何可能出错的东西都会出问题的”),这两个线程可能会同时发生。 在一些广泛使用的集合(如ArrayListHashSetHashMap等)进行结构修改的情况下,这可能会导致ConcurrentModificationException

很难完全防止这个问题:

  • 您可以logging同步要求,例如,插入“您必须在修改此集合之前进行同步”或“先获取bloolocking”,但这要依靠用户来发现,阅读,理解和应用指令。

    javax.annotation.concurrent.GuardedBy注释,它可以帮助以标准的方式logging这个注释; 那么问题是你必须有一些方法来检查工具链中注释的正确使用。 例如,您可能可以使用Google的errorprone ,它可以在某些情况下检查,但并不完美 。

  • 对于集合的简单操作,可以使用Collections.synchronizedXXX工厂方法,它们包装一个集合,以便每个方法调用都首先在底层集合上进行SynchronizedCollection.add ,例如SynchronizedCollection.add方法 :

     @Override public boolean add(E e) { synchronized (mutex) { return c.add(obj); } } 

    其中mutex是同步的实例(通常是SynchronizedCollection本身), c是包装的集合。

    这种方法的两个注意事项是:

    1. 你必须小心,包装的集合不能以任何其他方式访问,因为这将允许非同步访问,原来的问题。 这通常通过在施工中立即包装收集来实现:

       Collections.synchronizedList(new ArrayList<T>()); 
    2. 同步应用于每个方法调用,所以如果你正在做一些复合操作,例如

       if (c.size() > 5) { c.add(new Frob()); } 

      那么在整个操作过程中,您不具有独占访问权限,只能分别调用size()add(...)调用。

      为了在复合操作的持续时间内获得互斥访问,您需要在外部进行同步,例如synchronized (c) { ... } 。 这需要你知道正确的事情来同步,但是,可能或不可能是c