Jagaran
Jagaran

Reputation: 176

Concurrent Modification Exceptions

I am getting the following java.util.ConcurrentModificationException on this method

private AtomicReference<HashMap<String, Logger>> transactionLoggerMap = new AtomicReference<HashMap<String,Logger>>();

public void rolloutFile() {

    // Get all the loggers and fire a temp log line.
    Set<String> transactionLoggerSet = (Set<String>) transactionLoggerMap.get().keySet();
    Iterator<String> transactionLoggerSetIter = transactionLoggerSet.iterator();
    while(transactionLoggerSetIter.hasNext()){
        String key = (String) transactionLoggerSetIter.next();
        Logger txnLogger = transactionLoggerMap.get().get(key);
        localLogger.trace("About to do timer task rollover:");
        txnLogger.info(DataTransformerConstants.IGNORE_MESSAGE);
    }
}

Please suggest, if I am using a Atomic Reference, how do i get a como?

Upvotes: 2

Views: 880

Answers (4)

Ravi
Ravi

Reputation: 553

Remove the redundant Set<String> transactionLoggerSet = (Set<String>) transactionLoggerMap.get().keySet(); You would still have to use synchronization as you are iterating over the map. SynchronizedMap guarentees consistency for its API methods. For the rest, you would need to do client side synchronization

Upvotes: 0

Maybe you can consider iterating over a local copy of the collection instead of the same collection. It would be an easy way to ensure your collection will not be modified while you're looping over it. It is advisable to use immutable objects on a multi-threaded environment and you prevent this kind of problems for free.

Hope it helps.

Upvotes: 1

Gray
Gray

Reputation: 116938

A ConcurrentModificationException means that you have modified the collection outside of the iterator. I don't see any modifications in your loop so I assume that there is another thread that is also adding or removing from the transactionLoggerMap at the same time you are iterating across it.

Even though you have it wrapped in an AtomicReference, you still cannot have two threads making changes to the same unsynchronized collection at the same time. AtomicReference does not synchronize the object it is wrapping -- it just gives you a way to atomically get and set that reference.

You will need to make this a synchronized collection either by using the ConcurrentHashMap class or wrapping your HashMap using the Collections.synchronizedMap(map) method.

Upvotes: 9

Mattias Isegran Bergander
Mattias Isegran Bergander

Reputation: 11899

Because you are not protecting against concurrent modifications during your iteration. The Atomic reference only makes sure you get your Map (and it's contents).

Upvotes: 1

Related Questions