Reputation: 69
I need to add a static thread safe HashMap. I have something like this -
private static Map<String, ConcurrentHashMap<Integer, ClassA>> myCache =
new ConcurrentHashMap<String, ConcurrentHashMap<Integer, ClassA>>();
Even though I am using ConcurrentHashMap, I see that if main thread is adding element in the myCache, and when the same is accessed in other thread even at later time, it does not have the latest data in the myCache object. For e.g
Thread 1: Adds entry to the map
myCache = {a1={1=com.x.y.z.ClassA@3ec8b657}}
Thread 2: Access the same key a1
. But it does not see the data added by Thread 1. Rather it sees empty value for this key myCache = {a1={}}
As a result, data is getting corrupted. Entries added for the a1
key in Thread 1 are not visible in Thread 2.
Thanks in advance for any pointers on how can I update this map in thread safe manner.
Upvotes: 0
Views: 1459
Reputation: 1760
I've never had good results with ConcurrentHashMap. When I need thread safety, I usally do something like this:
public class Cache<K, V> {
private Map<K, V> cache = new HashMap<>();
public V get(K key) {
synchronized (cache) {
return cache.get(key);
}
}
public void put(K key, V value) {
synchronized (cache) {
cache.put(key, value);
}
}
}
Upvotes: 2
Reputation: 116908
Even though I am using ConcurrentHashMap, I see that if main thread is adding element in the myCache, and when the same is accessed in other thread even at later time, it does not have the latest data in the myCache object.
ConcurrentHashMap
is running in a large number of applications around the world at this instance. If your fairly typical use case didn't work appropriately, many critical systems would be failing.
Something is going on but chances are high that it is nothing to do with ConcurrentHashMap
. So here are some questions for you to help you debug your code:
ConcurrentHashMap
doesn't save you from race conditions in your code.hashcode()
or equals()
functions of the key object? By default the hashcode()
and equals()
methods are for the object instance and not the object value. See the consistency requirements.ConcurrentHashMap
. For example testing for existence of a cache entry and then making another call to put the value? You should be using putIfAbsent(...)
or the other atomic calls if so.If you edit your post and show a small sample of your code with the key object, the real source of the issue may be revealed.
Upvotes: 4
Reputation: 38320
The @Ryan answer is essentially correct.
Remember that you must proxy every Map
method that you wish to use
and you must synchronize to the cashe
element within every proxied method.
For example:
public void clear()
{
synchronized(cache)
{
cache.clear();
}
}
Upvotes: 1