同步集合中的ConcurrentModificationException

时间:2017-06-09 09:15:03

标签: java

我正在使用SynchronizedCollection.containsAll面临的问题是当我运行以下代码时,我得到ConcurrentModification Exception

从我的理解代码应该终止,没有任何例外。

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();
    }

}

有人可以帮助我理解为什么我会得到这个例外。

2 个答案:

答案 0 :(得分:2)

根据the documentation of Collections::synchronizedList

  

当迭代它时,用户必须手动同步返回的列表。

在您的示例中,当您运行sl.containsAll(sl2)时,您将在sl2上进行迭代,而无需在sl2上进行同步。这无疑是containsAll方法的实现细节,但it is clearly indicated in the javadoc

  

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

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

答案 1 :(得分:0)

我检查了代码,我认为异常是有意的,但如果是当前代码

public boolean containsAll(Collection<?> coll) {
synchronized(mutex) {return c.containsAll(coll);}
        }

更改为....

public boolean containsAll(Collection<?> coll) {
synchronized(mutex) {
               synchronized(coll) {
              return c.containsAll(coll);}}
        }

然后问题就解决了。