我的代码类似于以下内容:
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
。我可以确定这两种方法会在cache
和FREESPACE
同步吗?此外,checkFreeSpace()
是多线程安全的,即我可以确定一次只能调用一次此方法吗?可以改进此代码的“多线程安全性”吗?
答案 0 :(得分:3)
要完全回答您的问题,您需要显示thereIsSomethingToDelete()和deleteSomething()方法的实现。
鉴于checkFreeSpace是一个公共方法(它真的需要吗?),并且是不同步的,当putInCache()方法中的synchronized块运行时,它可能被另一个线程调用。这本身可能不会破坏任何东西,因为看起来checkFreeSpace方法只能增加可用空间量,而不是减少它。
什么会更严重(并且代码示例不允许我们确定这一点)是因为thereIsSomethingToDelete()和deleteSomething()方法没有正确地同步它们对缓存对象的访问,使用相同的Object锁由putInCache()使用。
答案 1 :(得分:2)
您通常不会直接在要控制访问权限的字段上进行同步。
您要同步访问的字段只能从同步块(在同一对象上)访问才能被视为线程安全。您已在putInCache()
中执行此操作。
因此,因为checkFreeSpace()
以不同步的方式访问共享状态,所以它不是线程安全的。