Welcome to the Java Programming Forums


The professional, friendly Java community. 21,500 members and growing!


The Java Programming Forums are a community of Java programmers from all around the World. Our members have a wide range of skills and they all have one thing in common: A passion to learn and code Java. We invite beginner Java programmers right through to Java professionals to post here and share your knowledge. Become a part of the community, help others, expand your knowledge of Java and enjoy talking with like minded people. Registration is quick and best of all free. We look forward to meeting you.


>> REGISTER NOW TO START POSTING


Members have full access to the forums. Advertisements are removed for registered users.

Results 1 to 3 of 3

Thread: Listeners, CopyOnWriteArrayList and removals

  1. #1
    Junior Member
    Join Date
    Aug 2010
    Posts
    2
    Thanks
    1
    Thanked 0 Times in 0 Posts

    Default Listeners, CopyOnWriteArrayList and removals

    A common suggestion to avoid ConcurrentModificationExceptions when iterating through listeners is to use a CopyOnWriteArrayList.

    But isn't there a possible issue that you will then call a listener that just de-registered? If the listening object wasn't expecting this, it could cause problems.

    What is the usual solution to this? Require any listener objects that de-register to keep a volatile state variable indicating their registration status, and to ignore the event if they aren't registered?


  2. #2
    Super Moderator copeg's Avatar
    Join Date
    Oct 2009
    Location
    US
    Posts
    5,103
    Thanks
    169
    Thanked 779 Times in 725 Posts
    Blog Entries
    5

    Default Re: Listeners, CopyOnWriteArrayList and removals

    Can you post some code that more clearly defines this? From what I gathered it seems you are talking about the following scenario: you have a List which contains an interface, iterating over that list to call the interface methods, then what may happen if an entry in the list is removed during iteration. To avoid synchronization issues in this scenario you can place the list in a synchronize block - synchronizing on the List object...any removal from the list in another thread will then have to wait until the lock is released (the synchronized block ends)

     
    synchronize(list){
        for ( int i = 0; i < list.size(); i++ ){
            list.get(i).....
        }
    }

  3. The Following User Says Thank You to copeg For This Useful Post:

    Richard (August 5th, 2010)

  4. #3
    Junior Member
    Join Date
    Aug 2010
    Posts
    2
    Thanks
    1
    Thanked 0 Times in 0 Posts

    Default Re: Listeners, CopyOnWriteArrayList and removals

    Thanks for the response. I found another thread discussing the same thing which may provide some background:
    https://www.ibm.com/developerworks/f...4954&#13754954

    Your response is on the right track. I have an object that needs to inform others when it changes. It allows others to register a listener. E.g. object is a model, various other objects need to know when the model changes. The listeners are stored in some collection (my suggestion was a CopyOnWriteArrayList, your response used a List). When a change occurs, the object must call each listener.

    If you just store the listeners in a list, and use an iterator to go through them, you are at risk of getting a Concurrent ModificationException if either another thread or one of the listeners itself either add or remove a listener. I can see a few ways to prevent this.

    1) synchronize on the list (call this lock A) when doing an add, remove or looping through the list (as your response suggested).This introduces the risk of deadlock, e.g.
    a) thread A has lock A and is looping through the listeners
    b) thread B has lock B, tries to add/remove a listener and therefore blocks on lock A
    c) a listener (running in thread A) tries to acquire lock B

    2) use a CopyOnWriteArrayList to store the listeners. This introduces the problem of my original post.
    a) thread A is looping through the listeners (no lock involved)
    b) thread B (or code called from the listener) removes a listener that hasn't yet been called.
    c) thread A is still using an old copy of the list of listeners (since the COWAL uses a snapshot iterator), so it then calls the listener that was already removed.

    I'm coming to the conclusion you can't make this bullet proof without placing some restrictions on the listeners. For example, the listener can't do anything that will add/remove a listener. Or the listener must be robust against being called after it was removed.
    Last edited by Richard; August 5th, 2010 at 02:14 PM. Reason: typos

Similar Threads

  1. Action Listeners and Key Listeners Help
    By xctive in forum What's Wrong With My Code?
    Replies: 3
    Last Post: November 18th, 2010, 08:27 AM
  2. Menu Event Listeners
    By Gondee in forum What's Wrong With My Code?
    Replies: 4
    Last Post: June 16th, 2010, 03:08 PM