yurloc / iypt-planner

Helps organizers of IYPT tournament schedule juries
4 stars 0 forks source link

java.util.ConcurrentModificationException #25

Closed yurloc closed 9 years ago

yurloc commented 11 years ago

java.util.ConcurrentModificationException at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:819) at java.util.ArrayList$Itr.next(ArrayList.java:791) at java.util.Collections$UnmodifiableCollection$1.next(Collections.java:1067) at org.iypt.planner.gui.PlannerWindow.solutionChanged(PlannerWindow.java:434) at org.iypt.planner.gui.PlannerWindow$SolverListener$1.run(PlannerWindow.java:523) at org.apache.pivot.wtk.ApplicationContext$QueuedCallback.run(ApplicationContext.java:1557) at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:251) at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:721) at java.awt.EventQueue.access$200(EventQueue.java:103) at java.awt.EventQueue$3.run(EventQueue.java:682) at java.awt.EventQueue$3.run(EventQueue.java:680) at java.security.AccessController.doPrivileged(Native Method) at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76) at java.awt.EventQueue.dispatchEvent(EventQueue.java:691) at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:244) at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:163) at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:151) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:147) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:139) at java.awt.EventDispatchThread.run(EventDispatchThread.java:97)

yurloc commented 10 years ago

Fixed by 96f63c22ce7b580501e468d4891f28b1b38224a9.

yurloc commented 9 years ago

Observed again at e7dfdb143abb68b796fbdaf371b37ad451ff9726. I think the original fix didn't really help. The solutionChanged() method doesn't need to be synchronized because it accesses UI, therefore it must always run on the UI thread, in other words there are never multiple threads executing the method. The real problem is (probably) that before the UI thread starts iterating over constraint occurrences inside solutionChanged(), solver thread may already had found new best solution and has just started adding constraint occurrences into the CO list but has not finished it yet.

To prevent CME it is necessary to always return copy of the CO collection. However that doesn't prevent UI thread from accessing unfinished CO list. To avoid that, new object NewBestSolution must be published that would contain the solution (Tournament) together with a copy of the CO list.

The current stack trace:

java.util.ConcurrentModificationException
    at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859)
    at java.util.ArrayList$Itr.next(ArrayList.java:831)
    at java.util.Collections$UnmodifiableCollection$1.next(Collections.java:1067)
    at org.iypt.planner.gui.PlannerWindow.solutionChanged(PlannerWindow.java:377)
    at org.iypt.planner.gui.PlannerWindow$SolverListener$1.run(PlannerWindow.java:556)
    at org.apache.pivot.wtk.ApplicationContext$QueuedCallback.run(ApplicationContext.java:1607)
    at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:312)
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:745)
    at java.awt.EventQueue.access$300(EventQueue.java:103)
    at java.awt.EventQueue$3.run(EventQueue.java:706)
    at java.awt.EventQueue$3.run(EventQueue.java:704)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:715)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:242)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:161)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:150)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:146)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:138)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:91)