Java 同步集合中的ConcurrentModificationException

Java 同步集合中的ConcurrentModificationException,java,Java,我使用的是SynchronizedCollection.containsAll问题是,当我运行以下代码时,我遇到了ConcurrentModification异常 据我所知,代码应该毫无例外地终止 public class Main { public static void main(String[] args) { List l1 = new LinkedList(), l2 = new LinkedList(); for (int i = 0; i

我使用的是
SynchronizedCollection.containsAll
问题是,当我运行以下代码时,我遇到了
ConcurrentModification异常

据我所知,代码应该毫无例外地终止

public class Main {

    public static void main(String[] args) {
        List l1 = new LinkedList(), l2 = new LinkedList();
        for (int i = 0; i < 100000; i++) {
            l1.add("" + i);
        }
        for (int i = 0; i < 100000; i++) {
            l2.add("" + i);
        }
        // reverse to make the search take a little longer
        Collections.reverse(l2);
        final List sl1 = Collections.synchronizedList(l1);
        final List sl2 = Collections.synchronizedList(l2);

        new Thread() {
            public void run() {
                // synchronized (sl2) {
                sl1.containsAll(sl2);
                // }
            }
        }.start();
        new Thread() {
            public void run() {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                }
                sl2.add("3");
            }
        }.start();
    }

}
公共类主{
公共静态void main(字符串[]args){
列表l1=新链接列表(),l2=新链接列表();
对于(int i=0;i<100000;i++){
l1.添加(“+i”);
}
对于(int i=0;i<100000;i++){
l2.添加(“+i”);
}
//反转以使搜索花费更长的时间
收藏。反面(l2);
最终列表sl1=Collections.synchronizedList(l1);
最终列表sl2=Collections.synchronizedList(l2);
新线程(){
公开募捐{
//已同步(sl2){
sl1.containsAll(sl2);
// }
}
}.start();
新线程(){
公开募捐{
试一试{
睡眠(100);
}捕捉(中断异常e){
}
sl2.添加(“3”);
}
}.start();
}
}
有人能帮我理解为什么会出现这种异常。

根据

public class Main {

    public static void main(String[] args) {
        List l1 = new LinkedList(), l2 = new LinkedList();
        for (int i = 0; i < 100000; i++) {
            l1.add("" + i);
        }
        for (int i = 0; i < 100000; i++) {
            l2.add("" + i);
        }
        // reverse to make the search take a little longer
        Collections.reverse(l2);
        final List sl1 = Collections.synchronizedList(l1);
        final List sl2 = Collections.synchronizedList(l2);

        new Thread() {
            public void run() {
                // synchronized (sl2) {
                sl1.containsAll(sl2);
                // }
            }
        }.start();
        new Thread() {
            public void run() {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                }
                sl2.add("3");
            }
        }.start();
    }

}
用户在遍历返回的列表时,必须手动同步该列表

在您的示例中,当您运行
sl.containsAll(sl2)
时,您迭代
sl2
,而不在
sl2
上同步。这无疑是
containsAll
方法的一个实现细节,但是:

此实现迭代指定的集合,依次检查迭代器返回的每个元素,以查看它是否包含在此集合中


您可以通过在
sl2
上同步来解决此问题(即,取消注释您已注释掉的代码)。

我检查了代码,我认为存在异常,但如果当前代码

public boolean containsAll(Collection<?> coll) {
synchronized(mutex) {return c.containsAll(coll);}
        }
public boolean containsAll(集合coll){
已同步(互斥){返回c.containsAll(coll);}
}
已更改为

public boolean containsAll(Collection<?> coll) {
synchronized(mutex) {
               synchronized(coll) {
              return c.containsAll(coll);}}
        }
public boolean containsAll(集合coll){
已同步(互斥){
同步(coll){
返回c.containsAll(coll);}
}

然后问题就会解决。

您读过
Collections.synchronizedList()
的javadoc吗?为什么您认为sl1与sl2同步?而不是
Thread.sleep(100)将其更改为
线程睡眠(1000)coll
是一个同步的集合。