Azimuth
Azimuth

Reputation: 2698

Synchronizing on two or more objects (Java)

I have code similar to following:

public class Cache{
 private final Object lock = new Object();
 private HashMap<Integer, TreeMap<Long, Integer>> cache = 
  new HashMap<Integer, TreeMap<Long, Integer>>();
 private AtomicLong FREESPACE = new AtomicLong(102400);

 private void putInCache(TreeMap<Long, Integer> tempMap, int fileNr){
  int length; //holds the length of data in tempMap
  synchronized(lock){
   if(checkFreeSpace(length)){
    cache.get(fileNr).putAll(tmpMap);
    FREESPACE.getAndAdd(-length);
   }
  }
 }

 private boolean checkFreeSpace(int length){      
  while(FREESPACE.get() < length && thereIsSomethingToDelete()){
   // deleteSomething returns the length of deleted data or 0 if 
   // it could not delete anything
   FREESPACE.getAndAdd(deleteSomething(length));
  }
  if(FREESPACE.get() < length) return true;
  return false;
 }
}

putInCache is called by about 139 threads a second. Can I be sure that these two methods will synchronize on both cache and FREESPACE? Also, is checkFreeSpace() multithread-safe i.e can I be sure that there will be only one invocation of this method at a time? Can the "multithread-safety" of this code be improved?

Upvotes: 2

Views: 4307

Answers (2)

Henry
Henry

Reputation: 1489

To have your question answered fully, you would need to show the implementations of the thereIsSomethingToDelete() and deleteSomething() methods.

Given that checkFreeSpace is a public method (does it really need to be?), and is unsynchronized, it is possible it could be called by another thread while the synchronized block in the putInCache() method is running. This by itself might not break anything, since it appears that the checkFreeSpace method can only increase the amount of free space, not reduce it.

What would be more serious (and the code sample doesn't allow us to determine this) is if the thereIsSomethingToDelete() and deleteSomething() methods don't properly synchronize their access to the cache object, using the same Object lock as used by putInCache().

Upvotes: 3

Martin OConnor
Martin OConnor

Reputation: 3593

You don't usually synchronize on the fields you want to control access to directly. The fields that you want to synchronize access to must only be accessed from within synchronized blocks (on the same object) to be considered thread safe. You are already doing this in putInCache(). Therefore, because checkFreeSpace() accesses shared state in an unsynchronized fashion, it is not thread safe.

Upvotes: 2

Related Questions