当我的程序中的所有方法都同步时,是否有可能出现 ConcurrentModificationException?

发布于 2024-12-21 23:23:42 字数 162 浏览 2 评论 0原文

即使我同步了整个程序的所有方法(包括静态方法和 main 方法),我还是收到了 ConcurrentModificationException 。

我没有隐藏的迭代器。

  1. 这怎么可能?
  2. 这是什么意思?
  3. 我该如何修复它?

I get a ConcurrentModificationException even though I made all the methods of the whole program synchronized (including static methods and the main method).

I don't have hidden iterators.

  1. How is that even possible?!
  2. What does it mean?
  3. How can I fix it?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

请叫√我孤独 2024-12-28 23:23:42
  1. ConcurrentModificationException 可能是由同一个线程在迭代集合时操作集合引起的。
  2. 这意味着在迭代集合时不要更改集合,除非通过迭代器。 remove() 或 ListIterator.add() 方法
  3. 请参见 2。
  1. A ConcurrentModificationException can be caused by the same thread manipulating a collection while iterating over it
  2. It means don't change collections while iterating over them, except through the Iterator.remove() or ListIterator.add() methods
  3. see 2.
兮颜 2024-12-28 23:23:42

ConcurrentModificationException 与同步无关。

它与迭代集合时修改集合有关。正如 Lie Ryan 指出的那样,完整的堆栈跟踪将帮助我们指出你是如何得到它的。

通常,要解决此问题,您在迭代集合时不得修改集合本身。

ConcurrentModificationException is NOT related to synchronization.

It's related to modifying a collection while iterating through it. As Lie Ryan points out, a full stack trace would help us point out how you got it.

Generally, to fix this, you must not modify the collection itself while iterating through it.

热鲨 2024-12-28 23:23:42

如果你运行这个

List<Object> list = new ArrayList<Object>();
for(Object obj : list)
    list.remove(obj);

你会得到一个commodification。如果不使用适当的函数,则无法在迭代集合时更改集合。

可以使用以下方法解决此问题:

List<Object> list = new ArrayList<Object>();
for(Iterator<Object> itr = list.iterator(); itr.hasNext();)
    itr.remove();

If you run this

List<Object> list = new ArrayList<Object>();
for(Object obj : list)
    list.remove(obj);

You will get a comodification. You cannot alter a collection while iterating over it without using the appropriate functions.

This can be resolved using the following:

List<Object> list = new ArrayList<Object>();
for(Iterator<Object> itr = list.iterator(); itr.hasNext();)
    itr.remove();
伤感在游骋 2024-12-28 23:23:42

好吧,首先,如果你看到了,这是可能的:如果鸟书和鸟不同意,就相信鸟。

现在,这怎么可能发生呢?如果没有看到您的代码,很难准确地说出,但异常堆栈跟踪将指向它发生的位置;你在周围看到了什么?

一般来说,显然,当您有并发访问时,就会发生这种情况。当您找到发生这种情况的位置时,问问自己哪些线程可能会到达那里。

Well, to start with, if you're seeing it, it's possible: if the bird book and the bird disagree, believe the bird.

Now, how can it happen? Hard to say exactly without seeing your code, but the exception stacktrace will point to the place it happened; what do you see around that?

In general, it's going to happen when you have, obviously, concurrent accesses. When you find the place in which it's happening, ask yourself what threads could be getting there.

滿滿的愛 2024-12-28 23:23:42

当您迭代集合并在此期间从该集合中删除条目时,您会遇到此异常。

例如,

Collection<Object> objects = new ArrayList<Objects>(Arrays.asList("a","b"));
for (Object o : objects) {
    objects.remove(o); //throws exception
}

您必须将要删除的内容添加到另一个集合中,并在完成列表迭代后删除它们。
否则,您可以通过 iterator() 迭代对象集合,并在当前迭代器上调用 remove() 。

You get this exception when you're iterating over a collection and during this you remove an entry from this collection.

e.g.

Collection<Object> objects = new ArrayList<Objects>(Arrays.asList("a","b"));
for (Object o : objects) {
    objects.remove(o); //throws exception
}

You must add the ones you want to remove to another collection and remove them after your finished iterating over the list.
Otherwise, you iterate over the objects collection via it's iterator() and call remove() on the current iterator.

似梦非梦 2024-12-28 23:23:42

同步方法会在其运行的对象实例上放置一个锁。

如果对象 A 和 B 访问同一个集合,则 A#doStuff 和 B#doStuff 是否同步并不重要 - 它们仍然可以并发执行。

要锁定集合,您可能需要锁定集合本身:方法体中的synchronized(collection),或Java 5 互斥体(更好)。

(事实上​​,正如其他人指出的那样,即使在单个线程中也可能出现 ConcurrentModificationException )。

A synchronized method places a lock on the object instance it's running with.

If objects A and B access the same collection, it doesn't matter if A#doStuff and B#doStuff are synchronized - they can still execute concurrently.

To lock the collection, you probably want a lock on the collection itself: synchronized(collection) in the method bodies, or a Java 5 mutex (better).

(that and the fact that you can have ConcurrentModificationException even in a single thread as others have pointed out).

野味少女 2024-12-28 23:23:42

ConcurrentModificationException 的 javadoc 包含答案:

请注意,此异常并不总是表明对象已被不同线程同时修改。如果单个线程发出一系列违反对象约定的方法调用,则该对象可能会抛出此异常。例如,如果线程在使用快速失败迭代器迭代集合时直接修改集合,则迭代器将抛出此异常。

解决这个问题的方法就是不要这样做。

即,(正如其他人所指出的)如果您需要同时迭代和修改,请使用迭代器提供的方法,而不是直接修改集合。

The javadoc for ConcurrentModificationException contains the answer:

Note that this exception does not always indicate that an object has been concurrently modified by a different thread. If a single thread issues a sequence of method invocations that violates the contract of an object, the object may throw this exception. For example, if a thread modifies a collection directly while it is iterating over the collection with a fail-fast iterator, the iterator will throw this exception.

The way to fix it is to not do that.

I.e., (as others have noted) if you need to simultaneously iterate and modify, use the methods supplied by the iterator rather than modifying the collection directly.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文