Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Synchronization in a HashMap cache

I've got a web application where people ask for resources. This resources are cached using a synchronized hash map for efficiency. The problem here is when two different requests come for the same uncached resource at the same time: the operation retrieving the resources takes up a lot of memory, so I want to avoid calling it more than once for the same resource.

Can somebody please tell me if there is any potential problem with the following snippet? Thanks in advance.

private Map<String, Resource> resources = Collections.synchronizedMap(new HashMap<String, Resource>());

public void request(String name) {

  Resource resource = resources.get(name);

  if (resource == null) {
    synchronized(this) {
      if (resources.get(name) == null) {
        resource = veryCostlyOperation(name); // This should only be invoked once per resource...
        resources.put(resource);
      } else {
        resource = resources.get(name);
      }
    }
  }

  ...

}
like image 691
user683887 Avatar asked Mar 30 '11 14:03

user683887


People also ask

What is HashMap synchronization?

Synchronization means controlling the access of multiple threads to any shared resource. A synchronized resource can be accessed by only one thread at a time. HashMap can be synchronized using the Collections.

What is cache synchronization?

An additional problem, beyond that of impedance mismatch, can occur because the cache used by an application may not be tightly integrated with an RDBMS. This problem is referred to as cache synchronization. It occurs after the relational data has been transformed into an object format placed in an application cache.

Why is HashMap not synchronized?

HashMap is non-synchronized. It is not thread-safe and can't be shared between many threads without proper synchronization code whereas Hashtable is synchronized. It is thread-safe and can be shared with many threads.

Is HashMap synchronous asynchronous?

2. Synchronized HashMap: Java HashMap is a non-synchronized collection class. If we need to perform thread-safe operations on it then we must need to synchronize it explicitly. The synchronizedMap() method of java.


1 Answers

One possible problem is that you create unnecessary contention by executing veryCostlyOperation() inside a synchronized block, so that many threads cannot retrieve their (independent) resources at the same time. This can be solved by using Future<Resource> as values of the map:

Map<String, Future<Resource>> map = new ConcurrentHashMap<String, Future<Resource>>();    
...
Future<Resource> r = map.get(name);
if (r == null) {
    FutureTask task = null;
    synchronized (lock) {
        r = map.get(name);
        if (r == null) {
            task = new FutureTask(new Callable<Resource>() {
                public Resource call() {
                    return veryCostlyOperation(name);
                }
            });
            r = task;
            map.put(name, r);
        }
    }
    if (task != null) task.run(); // Retrieve the resource
}

return r.get(); // Wait while other thread is retrieving the resource if necessary
like image 199
axtavt Avatar answered Sep 22 '22 06:09

axtavt