2

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?

1
  • (There is no point using AtomicLong in that code.) Commented Nov 27, 2009 at 17:31

2 Answers 2

3

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().

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for your reply. First of all, public is not a big issue because these two methods are only called by another method in the same class. As for thereIsSomethingToDelete() and deleteSomething(), I do not have these method in fact. Their logic is included to checkFreeSpace method but it would be too messy if I would put all code here. So let's just suppose those methods are properly synchronized.
Sorry, I chose wrong methods to ask questions about. Please take a look on edited version.
So presumably putInCache() is not really private then either (otherwise how could the class actually be used). I think then that the class is threadsafe as described, since all access to mutable state can only occur if a thread holds the lock established by the putInCache() synchronized block.
2

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.

2 Comments

what if I declare putInCache() as synchronized? Will that make both methods "safer"?
@Azimuth You need to protect access at the field level, which means all methods that access those fields need to synchronize on the same lock object. In short, you will need to add a synchronized block to the checkFreeSpace() too.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.