This discussion is archived
4 Replies Latest reply: Feb 3, 2012 6:09 AM by 796440 RSS

Multithreading - Concurrent modification exception

913819 Newbie
Currently Being Moderated
I am using multithreads. I have two classes.

1. FirstClass.java
In this class i just simply iterate through a collection without modifying it.

2. SecondClass.java
In this class the collection is created and modified


FirstClass.java
    public Set findExceptions(long id, Set rules, SecondClass mapC)
    {
         
         Set result = new HashSet();
         Set<Rule> existingRules = new HashSet(rules);
         Set allExceptions = mapC.findValidationExceptionsByMapObject(id); //this calls the below method in SecondClass.java
         Iterator exceptionIter = allExceptions.iterator();
         while (exceptionIter.hasNext()) {
            ValidationException valException = (ValidationException) exceptionIter.next();  //I get java exception here
             Rule rule = valException.rule();

             for (Rule existingRule : existingRules) {
                 if (existingRule.ruleCode().equals(rule.ruleCode())) {
                      result.add(valException);
                 }
             }
         }

         return result;
    }
SecondClass.java
     //declare the collection
     private final Map<Long, Set<ValidationException>> d_validationExceptionsByMapObject = new HashMap<Long,
        Set<ValidationException>>();
                

    public Set<ValidationException> findValidationExceptionsByMapObject(long mapObjectId)
    {
        Set<ValidationException> result;

        if (d_validationExceptionsByMapObject.containsKey(mapObjectId))
        {
            result = Collections.unmodifiableSet(d_validationExceptionsByMapObject.get(mapObjectId));
        }
        else
        {
            result = Collections.<ValidationException>emptySet();
        }

        return result;
    }

    public  void indexValidationException(ValidationException exception, long id)
    {
                d_validationExceptionsByMapObject.put(id, exception);
    }
The exception is occurring because while one thread is iterating through collection in findExceptions method, another thread is writing to the same collection(d_validationExceptionsByMapObject) in the SecondClass().  Can you suggest something ?

I am attaching the exception log
SEVERE: Error executing rules in thread
java.util.concurrent.ExecutionException: java.util.ConcurrentModificationException
     at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:222)
     at java.util.concurrent.FutureTask.get(FutureTask.java:83)
     at com.navtech.val.service.MultiThreadedDeltaValidationService.runDeltaValidationsInternal(MultiThreadedDeltaValidationService.java:134)
     at com.navtech.val.service.MultiThreadedDeltaValidationService.executeDeltaValidationsUsingThreads(MultiThreadedDeltaValidationService.java:89)
     at com.navtech.val.ValidationServiceImpl.getDeltaValidationResults(ValidationServiceImpl.java:2250)
     at com.navtech.val.ValidationServiceImpl.runDeltaValidations(ValidationServiceImpl.java:2215)
     at com.navtech.val.ValidationServiceImpl.validate(ValidationServiceImpl.java:2134)
     at com.navtech.bison.ui.common.mapmodel.MapModel.reindex(MapModel.java:3018)
     at com.navtech.bison.ui.common.mapmodel.MapModel.execute(MapModel.java:2652)
     at com.navtech.bison.ui.common.mapmodel.MapModel.execute(MapModel.java:2587)
     at com.navtech.atlas.NavLinkUpdateCommand.apply(NavLinkUpdateCommand.java:5739)
     at com.navtech.atlas.NavLinkViewController.applyButtonAP(NavLinkViewController.java:1645)
     at com.navtech.atlas.NavLinkViewController$14.actionPerformed(NavLinkViewController.java:1535)
     at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1995)
     at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2318)
     at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:387)
     at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:242)
     at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:236)
     at java.awt.AWTEventMulticaster.mouseReleased(AWTEventMulticaster.java:272)
     at java.awt.Component.processMouseEvent(Component.java:6216)
     at javax.swing.JComponent.processMouseEvent(JComponent.java:3265)
     at java.awt.Component.processEvent(Component.java:5981)
     at java.awt.Container.processEvent(Container.java:2041)
     at java.awt.Component.dispatchEventImpl(Component.java:4583)
     at java.awt.Container.dispatchEventImpl(Container.java:2099)
     at java.awt.Component.dispatchEvent(Component.java:4413)
     at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4556)
     at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4220)
     at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4150)
     at java.awt.Container.dispatchEventImpl(Container.java:2085)
     at java.awt.Window.dispatchEventImpl(Window.java:2475)
     at java.awt.Component.dispatchEvent(Component.java:4413)
     at java.awt.EventQueue.dispatchEvent(EventQueue.java:599)
     at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)
     at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)
     at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174)
     at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169)
     at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161)
     at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)
Caused by: java.util.ConcurrentModificationException
     at java.util.HashMap$HashIterator.nextEntry(HashMap.java:793)
     at java.util.HashMap$KeyIterator.next(HashMap.java:828)
     at java.util.Collections$UnmodifiableCollection$1.next(Collections.java:1010)
     at com.navtech.val.validation.FirstClass.findExceptions(FirstClass.java:187)
     at com.navtech.val.validation.DeltaLinkAdjacentLinkCondition.runAllDeltas(DeltaLinkAdjacentLinkCondition.java:119)
     at com.navtech.val.DeltaValidationCommand.exec(DeltaValidationCommand.java:80)
     at com.navtech.val.service.MultiThreadedDeltaValidationService.executeDeltaValidationCommand(MultiThreadedDeltaValidationService.java:264)
     at com.navtech.val.service.MultiThreadedDeltaValidationService$InThreadDeltaValidationCallable.call(MultiThreadedDeltaValidationService.java:213)
     at com.navtech.val.service.MultiThreadedDeltaValidationService$InThreadDeltaValidationCallable.call(MultiThreadedDeltaValidationService.java:1)
     at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
     at java.util.concurrent.FutureTask.run(FutureTask.java:138)
     at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
     at java.lang.Thread.run(Thread.java:619)

Edited by: 910816 on Jan 29, 2012 5:44 AM
  • 1. Re: Multithreading - Concurrent modification exception
    796440 Guru
    Currently Being Moderated
    910816 wrote:
    Can you suggest something ?*
    I suggest in the future you do some research, like reading the Exception's documentation, googling for that exception and how to prevent it, and studying the basics of multithreading before writing multithreaded code. :-)

    I also suggest you either a) Synchronize all access to that collection explicitly, b) Use one of the Collections.synchronizedXxx() methods (which will still require syncing around the iteration), or c) Use an appropriate java.util.concurrent class (which may still require some syncing--I don't know as I haven't read your code).

    I also recommend you use code tags in the future when posting code, so that it will be readable: https://forums.oracle.com/forums/ann.jspa?annID=1429
  • 2. Re: Multithreading - Concurrent modification exception
    913819 Newbie
    Currently Being Moderated
    Tried something which works but it may not be a perfect fix.

    In FirstClass.java
    Changed this line
    Set allExceptions = mapC.findValidationExceptionsByMapObject(id);
    to
    Set allExceptions = new HashSet(mapC.findValidationExceptionsByMapObject(id)); 
    So in other words, when faced with concurrency issues the best solution would be to synchronize blocks of code that modifies the variables but in situation like below where modification of a variable is happening in one class and it is being simply read in another class, you can make a copy of the variable at the time of reading.

    Abhi
  • 3. Re: Multithreading - Concurrent modification exception
    EJP Guru
    Currently Being Moderated
    Not a solution. It just moves the problem, to inside the constructor new HashSet(Set). That iterates over the supplied Set to get its contents.
  • 4. Re: Multithreading - Concurrent modification exception
    796440 Guru
    Currently Being Moderated
    910816 wrote:
    So in other words, when faced with concurrency issues the best solution would be to synchronize blocks of code that modifies the variables
    No. The only solution is to synchronize all access to shared variables. ^1^
    but in situation like below where modification of a variable is happening in one class and it is being simply read in another class, you can make a copy of the variable at the time of reading.
    You mean make a copy of the object. Make sure you understand the difference between a variable (which just holds a reference) and the object it points to. Copying a variable does nothing here.

    In the case of copying the object, no that's not sufficient, because it's not an atomic operation, so you need to sync around that copy operation as well.

    When all is said and done, if you have shared data, use synchronization. Trying to find "tricks" to get around it will just make your code more complicated, and make it not work correctly.

    ^1^ In some cases, using volatile is sufficient, and since the java.util.concurrent stuff was added in 1.5, we can do away with a lot of syncing in our code. Those classes may or may not used "synchronized" in a given situation. Utimately, though it all boils down to the same thing.

Legend

  • Correct Answers - 10 points
  • Helpful Answers - 5 points