I am considering using EnumMap in a concurrent environment. However, the environment is atypical, here's why:
EnumMap is always full: there are no unmapped keys when the map is exposed to the concurrent environmentput() and get() operations will be used (no iterating over, no remove(), etc.)get() does not reflect a call to put() immediately or orderly.From what I could gather, including relevant method source code, this seems to be a safe scenario (unlike if iterations were allowed). Is there anything I might have overlooked?
In general, using non-thread-safe classes across threads is fraught with many problems. In your particular case, assuming safe publication after all keys have had values assigned (such that map.size() == TheEnum.values().length), the only problem I can see from a quickish glance of EnumMap's code in Java 1.6 is that a put may not ever get reflected in another thread. But that's only true because of the internals of EnumMap's implementation, which could change in the future. In other words, future changes could break the use case in more dangerous, subtle ways.
It's possible to write correct code that still contains data races -- but it's tricky. Why not just wrap the instance in a Collections.synchronizedMap?
Straight from the JavaDoc:
Like most collection implementations EnumMap is not synchronized. If multiple threads access an enum map concurrently, and at least one of the threads modifies the map, it should be synchronized externally. This is typically accomplished by synchronizing on some object that naturally encapsulates the enum map. If no such object exists, the map should be "wrapped" using the
Collections.synchronizedMap(java.util.Map<K, V>)method. This is best done at creation time, to prevent accidental unsynchronized access:
Map<EnumKey, V> m = Collections.synchronizedMap(new EnumMap<EnumKey, V>(...));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With