aspose file tools*
The moose likes Java in General and the fly likes How Iterate Synch'd List of Connections and close them? Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Java in General
Bookmark "How Iterate Synch Watch "How Iterate Synch New topic
Author

How Iterate Synch'd List of Connections and close them?

Dan Bizman
Ranch Hand

Joined: Feb 25, 2003
Posts: 387
I have a synchronized list of connections. I want to iterate through that list and close them all. However, it always throughs a java.util.ConcurrentModificationException even though I follow the rules in the java.sun.com tutorial:

It's the con.close() that causes the problem. When I move to the next item in the list, it throws the exception. Does anyone know how I can do this?
Dan Bizman
Ranch Hand

Joined: Feb 25, 2003
Posts: 387
Here's something else weird:
I print out the size of my list and it's 1!! So why is it trying to come back in to the list? Here's something else weird:
When I dod NOT close the connection, it does NOT come back in to the while loop. BUT if I close the connection, the while loop will continue around again. Why is this?
Dan Bizman
Ranch Hand

Joined: Feb 25, 2003
Posts: 387
OK, figured out something here:
If I remove the connection from the list first and THEN close it, there's no problem!
So I'm guessing that closing it somehow sets it null (?) which then removes it from the list without changing the size of the list (?) making it think there's still another item in the list? Does any of this sound remotely correct?
I've seen other people with code that closes the connection first then removes it - do they have bad code (and they just haven't hit the exception yet) or am I just doing something wrong here?
[ February 27, 2003: Message edited by: Dan Bizman ]
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
My guess is that somewhere you've got other code which is accessing idleConnections without using synchronization. This would mean that even though you synchronized the loop shown above, it doesn't matter since the other code simply ignores the synchronization. Why is this a problem when you close() first, but not if you remove the item from the Collection before closing? My guess is that close() is a time-intensive operation. When you finish with the collection before closing, you minimize the time between acquiring the Iterator and calling remove(). This minimizes (but not eliminates) the chance that another thread will modify the collection while you're still iterating. But if you call close() before remove(), you greatly increase the chance for the other thread to interfere with your iteration.
Based on this theory, you really need to find the other code that accesses the idleCollection without proper synchronization. Moving the close() method improves your chances of avoiding a problem, but does not guarantee you'll be OK. Furthermore if idleCollection ever has more than 1 Connection in it, your chances of ConcurrentModificationException will increase substantially, no matter where the close() has been moved.


"I'm not back." - Bill Harding, Twister
Dan Bizman
Ranch Hand

Joined: Feb 25, 2003
Posts: 387
But that's impossible (I think) because it's in a shutdown hook. Also, I have all my code logging what it's doing and before it hits the shutdown hook, everything else is quiet and all the connections closed. Yet, it still throws this error. Any ideas?
Dan Bizman
Ranch Hand

Joined: Feb 25, 2003
Posts: 387
I GOT IT!!! I GOT IT!!! And you're not going to believe this! My PoolManager test was using the MySQL ConnectionPoolDataSource:
com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource
Well, turns out they actually coded it backwards! See they use the same method to send an error event as a closed event, but the only way they distinguish is by an int which is either 1 or 2. Well, 2 means an error occurred and they mis-coded the close() method to send 2 instead of 1. So THAT is why I couldn't close the stupid thing and it kept throwing that problem! (So I recompiled their code, added it to the jar file and it works! Man what a BIG mistake in released code! how come no one ever noticed that?)
Now it DID make me see a problem with my code - I was not synchronizing the removal in my error-handling code. So now I have a question:
Let's say an error is thrown when I try to close it, it will call my event listener which, if in a synchronized call, I assume will wait for the first which is waiting for that - deadlock. So what's the solution? (The listener is the same class/object as the one that is trying to close everything)
karl koch
Ranch Hand

Joined: May 25, 2001
Posts: 388
hi

closing the connection can not set it to null and remove it from the list. it would need to assign null to your reference (con = null).
i agree with jim, there must be somebody else touching (adding/removing stuff) the idleConnections list. as an addition: close the connection in a try/catch block to make sure all connections are closed even if one close() operation throws an exception.
k
Dan Bizman
Ranch Hand

Joined: Feb 25, 2003
Posts: 387
OK, I'm confused because here's what happens:
1. synchronize block started on idleConnections
2. Inside block, I call close() on the conn
3. The close call throws error (because of bad MysqlPooledConnection code)
4. the error causes my object's event listener interface to be called (connectionErrorOccurred)
5. Inside the connectionErrorOccurred method, I start a synchronized block on idleConnections
6. In that block I remove the bad connection
7. It returns to the first method, still inside the block and tries to remove and gets an error
Why is this happening? They're both in a synchronized block, shouldn't the first block the second from being able to get inside it's block? Is it because it's in the same thread?
[ February 27, 2003: Message edited by: Dan Bizman ]
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
Is it because it's in the same thread?
Yup. A lock for a given monitor can be acquired multiple times by code run by a single thread - it just can't be acquired by a different thread until the original thread releases it. If a lock has been acquired n times, it must also be released n times before it's available to other threads.
 
Don't get me started about those stupid light bulbs.
 
subject: How Iterate Synch'd List of Connections and close them?