Can the following piece of code be rewritten w/o using Collections.synchronizedMap()
yet maintaining correctness at concurrency?
Collections.sy
If you are using Java 7 and above, this use case is solved in a thread-safe manner with ClassValue
https://docs.oracle.com/javase/7/docs/api/java/lang/ClassValue.html If you require the use of remove
, think carefully about concurrency and read the doc thoroughly.
If you are using Java 6 or below. No, you have to synchronize a WeakHashMap.
Guava's CacheBuilder class allows you to do this easily.
CacheBuilder.newBuilder().weakKeys().build()
Note that this changes key equality semantics to be ==
instead of .equals()
which will not matter in your case of using Class
instances but is a potential pitfall.
Cafeine is a popular competitor of Guava cache.
- keys automatically wrapped in weak references
- values automatically wrapped in weak or soft references
usage:
LoadingCache<Key, Graph> graphs = Caffeine.newBuilder()
.weakKeys()
.weakValues()
.build(key -> createExpensiveGraph(key));
Does wrapping the WeakHashMap in a synchronized map still work correctly for what you want to do, since the garbage collector can modify the weakreferences directly at anytime, bypassing the synchronized map wrapper? I think WeakHashMap only truly works in a single threaded model.
I don't believe there is. In fact the javadoc suggests using Collections.synchronizedMap()
"Like most collection classes, this class is not synchronized. A synchronized WeakHashMap may be constructed using the Collections.synchronizedMap method."
Does wrapping the WeakHashMap in a synchronized map still work correctly for what you want to do, since the garbage collector can modify the weakreferences directly at anytime, bypassing the synchronized map wrapper? I think WeakHashMap only truly works in a single threaded model.
As mentioned above, the documentation for WeakHashMap at https://docs.oracle.com/javase/7/docs/api/java/util/WeakHashMap.html specifically says:
"A synchronized WeakHashMap may be constructed using the Collections.synchronizedMap method"
Which implies to me that this technique must work in tandem with the garbage collector's behavior (unless the documentation is buggy!)