简体   繁体   中英

ComputeIfAbsent throwing concurrentModificationException

I have a Hashmap where I maintain mapping of different kinds of readers to their respective java class implementations. I have a multithreaded Java server which supports 32 types of readers.

You can assume every 30 seconds, getReader() is called internally by 1000s of objects for each type of reader.

Whenever I reduce the refresh time to 20 seconds, it starts throwing ConcurrentModificationException for some readers sporadically. Is it expected?

What difference does it make with decreasing the time period?

class Mapper {
    Map<String, Reader> READER = new HashMap<>();

    public static Reader getReader(type) {
        Reader reader = READER.computeIfAbsent(type, k -> new ReaderImpl());
    }
}

You should use a ConcurrentHashMap if your map can be accessed by multiple Threads.

Whenever I reduce the refresh time to 20 seconds, it starts throwing ConcurrentModificationException for some readers sporadically. Is it expected?

It might be just coincidence. If you reduce the time you just make it more probable that Threads will try to access the map and will break it because you are not using synchronized collection. There is also possibility that if you run your application enough times you will get it also for your 30 seconds refresh time. Debuging multithreaded applications is hard because you might think that your application is running okay - but in the end it turns out that for 1 out of 1000 you get an error because you handled multithreading the wrong way.

As Andy Turner pointed out correctly - you are lucky that ConcurrentModificationException appeared. If you receive no exception that does not mean the problem is not there. It would be worse if you received such error in your application when running in production.

Is it expected?

As it says in the Javadoc of HashMap (emphasis theirs):

Note that this implementation is not synchronized. If multiple threads access a hash map concurrently, and at least one of the threads modifies the map structurally, it must be synchronized externally. (A structural modification is any operation that adds or deletes one or more mappings; merely changing the value associated with a key that an instance already contains is not a structural modification.)

In terms of whether a ConcurrentModificiationException specifically is expected, don't know. What should be expected is that the behaviour is undefined .

If you're lucky, an exception occurs. Exceptions are good: they tell you you're doing something wrong. If you're less lucky, it silently fails. Who knows what will happen in your specific circumstances? Maybe it will work correctly, maybe it doesn't.

If you want your code to behave correctly, use the classes as they are documented.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM