为什么从多个线程修改何时ArrayList中没有抛出ConcurrentModificationException? [英] Why does ArrayList not throw ConcurrentModificationException when modified from multiple threads?

查看:161
本文介绍了为什么从多个线程修改何时ArrayList中没有抛出ConcurrentModificationException?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

ConcurrentModificationException的:此异常可能是由检测到对象的并发修改时,这种修改是不允许的方法抛出

ConcurrentModificationException : This exception may be thrown by methods that have detected concurrent modification of an object when such modification is not permissible.

以上是从的javadoc ConcurrentModificationException的定义。

Above is ConcurrentModificationException definition from javadoc.

于是,我尝试测试低于code:

So I try to test below code:

final List<String> tickets = new ArrayList<String>(100000);
for (int i = 0; i < 100000; i++) {
    tickets.add("ticket NO," + i);
}
for (int i = 0; i < 10; i++) {
    Thread salethread = new Thread() {
        public void run() {
            while (tickets.size() > 0) {
                tickets.remove(0);
                System.out.println(Thread.currentThread().getId()+"Remove 0");
            }
        }
    };
    salethread.start();
}

在code是简单。
10个线程请从ArrayList对象的元素。
可以肯定的是多个线程访问一个对象。但它运行正常。无异常。
为什么呢?

The code is simple. 10 threads remove the element from the arraylist object. It is sure that multiple threads access one object. But it runs OK. No exception is thrown. Why?

推荐答案

我引述的 的ArrayList 的Javadoc为了你的利益。解释你看到高亮显示的行为相关的部分。

I'm quoting a large section of the ArrayList Javadoc for your benefit. Relevant portions that explain the behavior you are seeing are highlighted.

注意,此实现不是同步的。如果多个线程
  同时访问一个ArrayList实例,并且该至少一个
  线程修改了该列表结构,它必须被同步
  外部
即可。 (结构上修改是指添加任何操作或
  删除一个或多个元件,或明确地调整大小背衬阵列;
  仅设置一个元素的值不是结构
  修改)。这一般是通过在一些同步操作来完成
  对象自然封装列表。如果不存在这样的对象,
  名单应该是包装使用Collections.synchronizedList
  方法。这最好在创建时进行,以prevent意外
  不同步访问列表:

Note that this implementation is not synchronized. If multiple threads access an ArrayList instance concurrently, and at least one of the threads modifies the list structurally, it must be synchronized externally. (A structural modification is any operation that adds or deletes one or more elements, or explicitly resizes the backing array; merely setting the value of an element is not a structural modification.) This is typically accomplished by synchronizing on some object that naturally encapsulates the list. If no such object exists, the list should be "wrapped" using the Collections.synchronizedList method. This is best done at creation time, to prevent accidental unsynchronized access to the list:

目录列表= Collections.synchronizedList(新的ArrayList(...));

List list = Collections.synchronizedList(new ArrayList(...));

此类的iterator和listIterator方法返回的迭代器
  是快速失败的:如果列表后随时修改结构
  迭代器创建,以任何方式除非通过迭代器自身的
  删除或添加方法,迭代器都将抛出
  ConcurrentModificationException的。因此,在并行的面
  修改,迭代器很快就会完全失败,而不是
  在一个不确定的时间任意冒险,不确定性的行为
  在未来的。

The iterators returned by this class's iterator and listIterator methods are fail-fast: if the list is structurally modified at any time after the iterator is created, in any way except through the iterator's own remove or add methods, the iterator will 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.

注意,迭代器的快速失败行为不能得到保证
  因为它是,一般来说,不可能作出任何硬性保证
  不同步并发修改的presence
。快速失败
  迭代器扔在尽最大努力ConcurrentModificationException的
  基础。因此,这将是错误的编写依赖程序
  于此异常它的正确性:的快速失败行为
  迭代器应该仅用于检测bug。

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.

的ArrayList通常会引发并发修改例外,如果你在结构修改列表中的同时通过迭代器访问它(但即使这不是一个绝对的保证)。请注意,在你的榜样,你是从列表中删除直接的元素,而没有使用的迭代器。

ArrayLists will generally throw concurrent modification exceptions if you modify the list structurally while accessing it through its iterator (but even this is not an absolute guarantee). Note that in your example you are removing elements from the list directly, and you are not using an iterator.

如果它逗你的想象力,你也可以浏览的实施<一个href=\"http://grep$c$c.com/file/repository.grep$c$c.com/java/root/jdk/openjdk/6-b14/java/util/ArrayList.java#ArrayList.remove%28int%29\"><$c$c>ArrayList.remove,以获得更好的理解它是如何工作的。

If it tickles your fancy, you can also browse the implementation of ArrayList.remove, to get a better understanding of how it works.

这篇关于为什么从多个线程修改何时ArrayList中没有抛出ConcurrentModificationException?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆