0

Good Day,

I am having concurrency problems with a LinkedList in Java. I have an Object type called "Connection" which has as a member variable LinkedList of "MessageHandlers" called "listeners". I then have two different threads, one modifying and one iterating over the same LinkedList.

I've seen many many other StackOverflow questions that suggest to use the sychronized block of code, but that doesn't appear to be helping it all. I've also try creating the LinkedList as a concurrent linked list, but I am still receiving the

 Exception in thread "Thread-1" java.util.ConcurrentModificationException

exception. Does anyone have any other suggestions to try? Here are some snipbits of my code...

public synchronized Object ReadObject() throws java.io.IOException
{
    Object obj = null;

    try
    {
        obj = input.readObject();

        synchronized(listeners)
        {
            Iterator<MessageHandler> i = listeners.iterator();

            while(i.hasNext())
            {
                i.next().MessageReceived(obj, this);
            }
        }
    } 
    catch (IOException e)
    {   
        e.printStackTrace();
        throw e;
    } 
    catch (ClassNotFoundException e)
    {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    return obj;
}

The above code is inside my connection object. It gets called from a function that has a socket's ObjectInputStream reading data from the socket."input" is an instance of ObjectInputStream.

public void addNewLoggedInUser(User user) throws Exception
{
    for(User u:loggedInUsers)
    {
        if(u == user)
        {
            throw new Exception("That user is already logged in");
        }
    }

    //Add the new users
    loggedInUsers.add(user);

    synchronized(user.getConnection().getListeners())
    {
        user.getConnection().getListeners().add(this);
    }

    this.SendGameStatusUpdateToAllLoggedinPlayers();
}

I then call the method user.getConnection().getListeners().add(this) and thus am getting the exception.

public Connection()
{
    //Initialize the variables to NULL
    socket              = null;
    output              = null;
    input               = null;
    receiveThread       = null;
    runReceiveThread    = false;
    listeners           = Collections.synchronizedList(new LinkedList<MessageHandler>());

    //Handle the ID counter. Now we have a unique ID for every connection that comes in
    connectionID = counterID;
    counterID = counterID + 1;
}

This is the constructor for the connection class. Notice he Collections.synchronizedList

Any ideas? Thank you very much for your help!

4
  • Are user.getConnection().getListeners() and listeners same instance in the synchronized block parameter? Commented Jun 15, 2012 at 3:44
  • ConcurrentModificationException is thrown when you've altered a list (added/removed elements) while iterating over it. You can cause this exception with a single thread. You shouldn't need any sort of concurrent collection unless there are multiple threads which access the list simultaneously. Commented Jun 15, 2012 at 3:45
  • ideone.com/pUPCn as an example. Commented Jun 15, 2012 at 3:53
  • @George Thanks! I didn't understand what you meant for the longest time thinking I didn't explain the code well enough, because I thought your response was way off. Turns out, you are exactly right! I didn't see what I was doing till I did it again on a smaller example and saw the same Exception being thrown. Thanks for your help George! Commented Jun 22, 2012 at 17:56

3 Answers 3

2

java.util.ConcurrentModificationException isn't really a threading issue. It is cause by modification of a list locked by it's iterator. I think you are calling addNewLoggedInUser() from MessageReceived(). This would cause the concurrent modification exception since the calling function already has iterator lock on the linkedlist.

Sign up to request clarification or add additional context in comments.

Comments

0

Go through BlockingQueue javadoc. It mentions a simple scenario as well that fits your requirements i.e.

class Producer implements Runnable {
  private final BlockingQueue queue;
  Producer(BlockingQueue q) { queue = q; }
  public void run() {
    try {
      while (true) { queue.put(produce()); }
    } catch (InterruptedException ex) { ... handle ...}
  }
  Object produce() { ... }
 }

 class Consumer implements Runnable {
   private final BlockingQueue queue;
   Consumer(BlockingQueue q) { queue = q; }
   public void run() {
     try {
       while (true) { consume(queue.take()); }
     } catch (InterruptedException ex) { ... handle ...}
   }
   void consume(Object x) { ... }
 }

 class Setup {
   void main() {
     BlockingQueue q = new SomeQueueImplementation();
     Producer p = new Producer(q);
     Consumer c1 = new Consumer(q);
     Consumer c2 = new Consumer(q);
     new Thread(p).start();
     new Thread(c1).start();
     new Thread(c2).start();
   }
 }

Comments

0

The synchronized blocks look like they should work. I would expect that there is activity in methods called from within the ReadObject synchronized block which modify the list. Do any of your MessageHandlers call or chain to a call to addNewLoggedInUser (or any other method that might update the listener list)?

If so, the thread would already have the monitor grabbed by the ReadObject synchronized block, and would be able to enter the block in addNewLoggedInUser.

1 Comment

yes, one of my MessageHandler's calls addNewLoggedInUser. I am not familiar with what the "monitor" is, so I will have to do some research on that. Thanks for the tip.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.