在两个或多个对象上同步(Java)

时间:2009-11-27 11:10:56

标签: java object synchronized multithreading

我的代码类似于以下内容:

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;
 }
}
每秒约有139个线程调用

putInCache。我可以确定这两种方法会在cacheFREESPACE同步吗?此外,checkFreeSpace()是多线程安全的,即我可以确定一次只能调用一次此方法吗?可以改进此代码的“多线程安全性”吗?

2 个答案:

答案 0 :(得分:3)

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

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

什么会更严重(并且代码示例不允许我们确定这一点)是因为thereIsSomethingToDelete()和deleteSomething()方法没有正确地同步它们对缓存对象的访问,使用相同的Object锁由putInCache()使用。

答案 1 :(得分:2)

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