1

我有一个存储数据并从许多线程中调用的类。ConcurrentModificationException尽管每次对我的访问Set都是同步的,但它失败了。

这怎么可能发生?同步应确保我的 Set 在迭代时不会更改...

这是我班级中所有访问Set...的函数

谁能告诉我这里出了什么问题?

private final Object mListenerLock = new Object();
private final Set<IRetainerBaseListener> mListeners = new HashSet<IRetainerBaseListener>();

protected final void register(IRetainerBaseListener listener)
{
    synchronized (mListenerLock)
    {
        mListeners.add(listener);
    }
}

protected final boolean unregister(IRetainerBaseListener listener)
{
    synchronized (mListenerLock)
    {
        return mListeners.remove(listener);
    }
}

private final void onObjectAdded(RKey key, Object data)
{
    synchronized (mListenerLock)
    {
        Iterator<IRetainerBaseListener> it = mListeners.iterator();
        while (it.hasNext())
        {
            IRetainerBaseListener listener = it.next();

            /* EDIT */
            /* I'm not changing the Set in here, never!!! */

            // I can't insert the if's, but I just check the interface class
            // and call one of the following methods:

            ((IRetainerListener) listener).onRetainerDataAdded(key, data);
            // or
            ((IRetainerSingleKeyListener) listener).onRetainerDataAdded(data);

        }
    }
}
4

2 回答 2

4

这不是线程安全的问题。

您在迭代您的集合时删除项目。这只能使用迭代器

 /*
  * *it* does not appreciate that you removed elements 
  * in another way than it.remove();
  * The iterator must do the add/remove operations itself
  * to guarantee that it will not break the iteration.
  */
 while (it.hasNext()) {
   IRetainerBaseListener listener = it.next();
   ...
 }
于 2013-10-02T13:36:48.600 回答
0

同步是确保没有其他线程正在执行,同时还试图在该操作期间保持“锁定”。

例子:

线程 A: synchronized(mListenerLock) { doSomething; }

线程 B:

同步(mListenerLock){doSomething; }

这样,A 或 B 都在做某事。一个必须等​​待另一个释放 mListenerLock 的二进制“锁”。

在您的情况下,您使用相同的线程来执行您的操作。因此,您会得到并发修改异常,因为您更改了列表的状态(删除对象),同时还对其进行了迭代。

ConcurrentModificationException 不涉及线程方面的并发问题。它只是说明,在使用列表(或相关对象)做一件事时,您的程序会做一些其他事情来阻止事情按预期工作。它是一种(防御性)安全机制,可防止常见错误发生而被忽视。

于 2013-10-02T13:45:29.397 回答