加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

java – 为什么ArrayList在从多个线程修改时不会抛出ConcurrentM

发布时间:2020-12-15 05:00:12 所属栏目:Java 来源:网络整理
导读:ConcurrentModificationException:当不允许此类修改时,检测到并发修改对象的方法可能抛出此异常. 以上是来自javadoc的ConcurrentModificationException定义. 所以我尝试测试下面的代码: final ListString tickets = new ArrayListString(100000);for (int
ConcurrentModificationException:当不允许此类修改时,检测到并发修改对象的方法可能抛出此异常.

以上是来自javadoc的ConcurrentModificationException定义.

所以我尝试测试下面的代码:

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

代码很简单.
10个线程从arraylist对象中删除元素.
确保多个线程访问一个对象.但它运行正常.没有异常被抛出.
为什么?

解决方法

为了您的利益,我引用了 ArrayList Javadoc的大部分内容.将突出显示解释您所看到的行为的相关部分.

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:

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

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.

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.

如果在通过迭代器访问列表时从结构上修改列表,ArrayLists通常会抛出并发修改异常(但即使这不是绝对的保证).请注意,在您的示例中,您将直接从列表中删除元素,并且您没有使用迭代器.

如果它引起你的兴趣,你也可以浏览ArrayList.remove的实现,以更好地理解它的工作原理.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读