concurrentmodification - java.util.ConcurrentModificationException upon LinkedHashSet iteration -
please, me understand error getting:
private void replayhistory() { synchronized (alarmshistory) { (alarmevent alarmevent : alarmshistory) { log.error("replayhistory " + alarmevent.type + " " + alarmevent.source); sendnotification(alarmevent.type, alarmevent.source, alarmevent.description, alarmevent.clearonotherstations, alarmevent.forceclearonotherstations); } } }
and method adds element it
private void addtoalarmshistory(alarmevent alarmevent) { synchronized (alarmshistory) { log.error("addtoalarmshistory " + alarmevent.type + " " + alarmevent.source); alarmshistory.add(alarmevent); } }
both methods , set
private volatile set<alarmevent> alarmshistory = new linkedhashset<alarmevent>();
are defined in
jmxgwreloadthread extends thread class
which inner class in
alarmmanager class
that has method
private void addtoreplayhistory(alarmevent alarmevent) { if ((jmxthread != null) && (jmxthread.isalive())) { jmxthread.addtoalarmshistory(alarmevent); } }
which being called different interfaces (cannot assure when , how often)
at point jmxthread started , calls replayhistory method
java.util.concurrentmodificationexception
thrown, root the
for (alarmevent alarmevent : alarmshistory) {
the code propably tries add element alarmshistory , when interator
java.util.concurrentmodificationexception @ java.util.linkedhashmap$linkedhashiterator.nextentry(linkedhashmap.java:390) @ java.util.linkedhashmap$keyiterator.next(linkedhashmap.java:401) @ alarmmanager$jmxgwreloadthread.replayhistory(alarmmanager.java:568) @ alarmmanager$jmxgwreloadthread.run(alarmmanager.java:532)
throws exception upon calling nextentry, should't synchronization prevent such issue?
logs show synchronization not work - replayhistory should iterate on elements (i can asure more 1 single heartbeat_info fm) it's interrupted addtoreplayhistory call.
2013-07-11 11:58:33,951 thread-280 error alarmmanager$jmxgwreloadthread.replayhistory(alarmmanager.java:570) - replayhistory heartbeat_info fm 2013-07-11 11:58:33,951 thread-280 error alarmmanager$jmxgwreloadthread.addtoalarmshistory(alarmmanager.java:550) - addtoalarmshistory heartbeat_info fm 2013-07-11 11:58:33,952 thread-280 error log4jconfigurator$uncaughtexceptionhandler.uncaughtexception(log4jconfigurator.java:253) - detected uncaught exception in thread: thread-280
one thing op (and people) should aware of:
concurrentmodificationexception has nothing multi-threading.
although multi-threading makes easier happen, core of problem has nothing multi-threading.
this caused scenario like,
- get iterator collection,
- before finish using iterator, collection structurally modified.
- keep on using iterator after 2. iterator detect collection structurally modified , throw out concurrentmodificationexception.
of course, not collection have such behavior, e.g. concurrenthashmap. definition of "structurally modified" different different collection too.
that means, have 1 thread, if like:
list<string> strings = new arraylist<string>(); //.... (string s: strings) { // iterating through collection strings.add("x"); // structurally modifying collection }
i concurrentmodificationexception happening in single thread.
there different ways solve problem, depending on requirement or problem. e.g.
- if due multi-thread access, proper synchronize access can 1 solution
- you may make use of collection iterator safe structural modification (e.g. concurrenthashmap)
- adjust logic either re-acquire iterator again if modified collection, or makes modification using iterator (some collection impls allows that), or make sure modification collection happens after finish using iterator.
given code seems having proper synchronization on alarmhistory
, there 2 directions want check
- is there possible modification of
alarmhistory
insidesendnotification()
? example, adding or removingalarmhistory
? - is there other possible unsynchronized access alarmhistory may modify structure?
Comments
Post a Comment