2

I know there are many questions asked on this but in my case i have it in a synchronised block and i am sure that nobody will be changing my array list.. But still i get this exception SOMETIMES if i am using for-each loop.. Why ?

Here is my code snippet

    final static Object mLock = new Object();
private static ArrayList<ConnectionAndAuthCallback> mCallbacks;
private void callAuthCallbacks() {
        synchronized (mLock) {

            if (mCallbacks != null)
                for (ConnectionAndAuthCallback calback : mCallbacks) { //here i get exception
                    calback.onAuthentication(mToken, calback.intent);
                }
        }
    }

here is the code i do on Callback

@Override
            public void onAuthentication(String token, Intent intent) {
                web.loadUrl("xyz.com");
                //unregister so that we wong get any exception or some more callbacks
                SameClass.unRegisterAuthCallbacks(this); 
            }

and in Unregister function

public static void unRegisterAuthCallbacks(ConnectionAndAuthCallback callback) {
        synchronized (mLock) {

            if (mCallbacks != null)
                if (mCallbacks.contains(callback)) {
                    mCallbacks.remove(callback); // This causing problem ?? In same thread "syncronised" wont work ??
                }
        }
    }
Charan Pai
  • 2,288
  • 5
  • 32
  • 44
  • 1
    Seems you are on wrong track. This code block should not cause this exception. – Pankaj Kumar Jun 16 '14 at 05:28
  • Where else in your code do you use `mCallbacks`? Are you iterating through `mCallbacks` at some point prior to the call to `callAuthCallbacks()`? – Alex Lockwood Jun 16 '14 at 05:29
  • You could always create your own `ArrayList` subclass that logs whenever the list is changed and by whom, and substitute that in. That's always a fun debugging technique. – awksp Jun 16 '14 at 05:31
  • Yes, mCallbacks gets iterated through in some other places too but they are too inside `sync` block – Charan Pai Jun 16 '14 at 05:32
  • Well, that's strange. Doesn't seem like the exception should be happening, and if none of us can reproduce your problem, helping you will be somewhat difficult... Try the `ArrayList` subclass thing and see if that helps? – awksp Jun 16 '14 at 05:35
  • Does that `onAuthentication` method modify the list in any way? – chrylis -cautiouslyoptimistic- Jun 16 '14 at 05:41
  • @chrylis Probably, `OnAuthentication` is a callback, in app on that callback i call unregister callback and in that i remove `this` object from list, But even remove code inside `synchronised` block with same static lock. – Charan Pai Jun 16 '14 at 05:50
  • I don't understand your explanation. Your `for` loop is holding an open iterator on the list; even if other code is operating under the same lock, if it modifies the list, you'll get the exception. – chrylis -cautiouslyoptimistic- Jun 16 '14 at 05:51
  • Aaaaand there we go. Your `ArrayList` indeed was being changed. `synchronized` of course won't work in the same thread. How do you synchronize one thread? – awksp Jun 16 '14 at 06:04
  • Yep, there's your problem. – shmosel Jun 16 '14 at 06:05
  • @user3580294 actually it gets called from many other thread also.. This is onee of the case i used so i used synchronised.. Thanks BTW. – Charan Pai Jun 16 '14 at 06:06
  • I see... Just be careful in the future. `synchronized` only protects against *external* threads. It won't prevent you from doing whatever you want inside a particular thread. – awksp Jun 16 '14 at 06:07
  • BUT why do i get this "sometimes" only ? – Charan Pai Jun 16 '14 at 06:12
  • Maybe because `mCallbacks` only sometimes contains `callback`? Or maybe because the callback to remove was at the end of `mCallbacks` for some portion of the time? – awksp Jun 16 '14 at 06:38

2 Answers2

1

You can't perform modifications on an ArrayList or remove() in this case that you are currently reading out of or looping through. Use iterators instead.

Check out this link. And this link.

Community
  • 1
  • 1
Ryhan
  • 1,815
  • 1
  • 18
  • 22
0

Answer was, In the same thread synchronised(){} wont work. Even if you think it works then there might be a dead lock.

In my case i was removing callback object from ArrayList in the same thread where i called callback.

Charan Pai
  • 2,288
  • 5
  • 32
  • 44