2

我有类似于以下的代码:

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每秒被大约 139 个线程调用。我可以确定这两种方法会在cache和上同步FREESPACE吗?另外,checkFreeSpace()多线程安全吗,即我可以确定一次只会调用一次此方法吗?这段代码的“多线程安全”可以改进吗?

4

2 回答 2

3

要完全回答您的问题,您需要展示 thereIsSomethingToDelete() 和 deleteSomething() 方法的实现。

鉴于 checkFreeSpace 是一个公共方法(它真的需要吗?)并且是不同步的,它可能会在 putInCache() 方法中的同步块运行时被另一个线程调用。这本身可能不会破坏任何东西,因为 checkFreeSpace 方法似乎只能增加可用空间量,而不能减少它。

如果 thereIsSomethingToDelete() 和 deleteSomething() 方法没有正确同步它们对缓存对象的访问,使用与使用相同的对象锁,则更严重(并且代码示例不允许我们确定这一点)放入缓存()。

于 2009-11-27T11:48:01.963 回答
2

您通常不会在要直接控制访问的字段上进行同步。您要同步访问的字段必须只能从同步块(在同一对象上)中访问,才能被视为线程安全。您已经在putInCache(). 因此,由于checkFreeSpace()以非同步方式访问共享状态,它不是线程安全的。

于 2009-11-27T11:21:13.090 回答