1

データを格納し、多くのスレッドから呼び出されるクラスがあります。ConcurrentModificationExceptionmy へのすべてのアクセス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

0

同期は、その操作中に「ロック」を保持しようとしながら、他のスレッドが実行されていないことを保証します。

例:

スレッド A: 同期 (mListenerLock) { doSomething; }

スレッド B:

同期 (mListenerLock) { doSomething; }

このようにして、A または B のいずれかが何かを行っています。一方は、もう一方が mListenerLock のバイナリ「ロック」を解放するのを待つ必要があります。

あなたの場合、まったく同じスレッドを使用してアクションを実行します。そのため、反復中にリストの状態を変更する (オブジェクトを削除する) ため、同時変更例外が発生します。

ConcurrentModificationException は、スレッドに関する同時実行の問題を参照していません。リスト (または関連するオブジェクト) で 1 つのことを実行しているときに、プログラムが意図したとおりに動作するのを妨げる他のことを行っていることを示しているだけです。これは、一般的なバグが見過ごされるのを防ぐための (防御的な) 安全メカニズムです。

于 2013-10-02T13:45:29.397 に答える