Java 删除同步方法中的ArrayList元素

Java 删除同步方法中的ArrayList元素,java,synchronization,Java,Synchronization,我有一个synchronized方法,它在ArrayList上运行,然后通过调用ArrayList.clear()删除其元素 为什么当多个线程调用此方法时,即使它是同步的,我也会得到ConcurrentModificationException 关键字synchronized不是用来避免此类错误的吗 public MyOuterClass { private class MyInnerClass implements MyCallback { private class MyIn

我有一个
synchronized
方法,它在
ArrayList
上运行,然后通过调用
ArrayList.clear()
删除其元素

为什么当多个线程调用此方法时,即使它是同步的,我也会得到
ConcurrentModificationException

关键字
synchronized
不是用来避免此类错误的吗

public MyOuterClass {

  private class MyInnerClass implements MyCallback {

    private class MyInnermostClass implements Runnable {

      @Override
      public void run() {

        if (condition) {
          myMethod();
        }
        else {
          synchronized (myArrayList) {
            myArrayList.add(new MyObject());
          }
      }
    }

    public void myCallback() {
      Thread myThread = new Thread(new MyInnermostClass());
      myThread.start();
    }
  }

  private ArrayList<MyObject> myArrayList;

  public MyClass() {
    myArrayList = new ArrayList<>();
  }

  private synchronized void myMethod() {
    for (MyObject o: myArrayList) {
      System.out.println(o);
    }
    myArrayList.clear();
  }
}

如果您的方法是从多个线程调用的,那么它肯定需要同步。然而,听起来好像有别的事情在发生

尽管名称不同,
ConcurrentModificationException
与线程并发性(本质上)无关。相反,当迭代器注意到它所迭代的集合以某种意外的方式发生了更改时,就会抛出它。例如,即使使用单线程应用程序,以下操作也会生成一个
ConcurrentModificationException

for (Object o : myArrayList) {
    if (shouldRemove(o)) {
        myArrayList.remove(o);
    }
}
处理这种情况的正确方法是使用显式迭代器并使用它删除元素:

for (Iterator<Object> iter = myArrayList.iterator(), Object o;
        iter.hasNext();
        o = iter.next())
{
    if (shouldRemove(o)) {
        iter.remove();
    }
}

这样,修改myArrayList的所有代码都会在list对象本身上同步。

这就是所有代码吗?或者您是否在for循环中执行其他操作,如添加/删除/修改元素?请发布堆栈跟踪和实际代码。通常
ConcurrentModificationException
与线程无关(尽管多线程可能会加剧问题)。它来自于在迭代器仍在积极迭代列表时修改列表。您发布的代码不会生成该异常;正在进行其他操作(可能与
已同步
)无关。同意,该代码不会导致出现所述异常。必须有一个代码,您可以在其中修改列表,由于异常与concurrentModificationCheck相关,因此您要么修改最终列表,要么如果不是最终列表,则必须使用迭代器在同步块时修改值,代码将正常工作。一定要让我们知道问题、完整堆栈跟踪或您没有放在这里的部分代码。@Tirafesi-我更新了我的答案,因为我有了更多信息。啊,我明白了。谢谢:D
for (Iterator<Object> iter = myArrayList.iterator(), Object o;
        iter.hasNext();
        o = iter.next())
{
    if (shouldRemove(o)) {
        iter.remove();
    }
}
private void myMethod() {
    synchronized (myArrayList) {
        for (MyObject o: myArrayList) {
            System.out.println(o);
        }
        myArrayList.clear();
    }
}