Deque remove 没有抛出 ConcurrentModificationException

Deque remove is not throwing ConcurrentModificationException

双端队列 class' Javadoc 说:

The iterators returned by this class's iterator method are fail-fast: If the deque is modified at any time after the iterator is created, in any way except through the iterator's own remove method, the iterator will generally throw a ConcurrentModificationException. Thus, in the face of concurrent modification, the iterator fails quickly and cleanly, rather than risking arbitrary, non-deterministic behavior at an undetermined time in the future.

但是,以下程序的行为不同:

[编辑]: 我在粘贴整个代码时遇到错误 "An error occurred submitting the edit"。哇!来吧。

// create an empty array deque with an initial capacity
Deque deque = new ArrayDeque(8);

// use add() method to add elements in the deque
deque.add(15);
deque.add(22);
deque.add(25);
deque.add(20);

System.out.println("printing elements using iterator:");
for(Iterator itr = deque.iterator();itr.hasNext();)  {
    System.out.println(itr.next());
    deque.remove(); //deque is modifed after the iterator is created
}

我预计它会抛出 ConcurrentModificationException,但它只是打印了以下输出:

printing elements using iterator:
15
22
25
20   

知道为什么吗?

看起来是因为你在删除它之前消耗了迭代器的第一个元素。如果您将代码更改为

for(Iterator itr = deque.iterator();itr.hasNext();)  {
    deque.remove(); 
    System.out.println(itr.next());
}

然后你会看到异常。您的原始实现确实与文档相矛盾。

但是,查看 ArrayDeque 的迭代器实现的实现,next() 方法有这样的代码:

E result = (E) elements[cursor];
// This check doesn't catch all possible comodifications,
// but does catch the ones that corrupt traversal
if (tail != fence || result == null)
    throw new ConcurrentModificationException();

请注意 Deque's Javadoc 中的以下段落:

Note that the fail-fast behavior of an iterator cannot be guaranteed as it is, generally speaking, impossible to make any hard guarantees in the presence of unsynchronized concurrent modification. Fail-fast iterators throw ConcurrentModificationException on a best-effort basis. Therefore, it would be wrong to write a program that depended on this exception for its correctness: the fail-fast behavior of iterators should be used only to detect bugs.