Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/341.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在两个或多个对象上同步(Java)_Java_Object_Synchronized_Multithreading - Fatal编程技术网

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

在两个或多个对象上同步(Java),java,object,synchronized,multithreading,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 AtomicL

我有如下类似的代码:

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;
 }
}
公共类缓存{
私有最终对象锁=新对象();
专用哈希映射缓存=
新的HashMap();
私有原子长自由空间=新原子长(102400);
私有void putInCache(树映射tempMap,int fileNr){
int length;//保存tempMap中数据的长度
已同步(锁定){
如果(选中自由空间(长度)){
cache.get(fileNr).putAll(tmpMap);
自由空间。getAndAdd(-length);
}
}
}
私有布尔校验空间(整数长度){
while(FREESPACE.get(){
//deleteSomething返回已删除数据的长度,如果是,则返回0
//它不能删除任何内容
getAndAdd(deleteSomething(length));
}
if(FREESPACE.get()

putInCache
每秒被大约139个线程调用。我是否可以确保这两个方法将在
缓存
自由空间
上同步?另外,
checkFreeSpace()
multi-thread是否安全,即我能否确保一次只调用一次此方法?这段代码的“多线程安全性”可以提高吗?

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

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

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


更严重的是(代码示例不允许我们确定这一点)如果thereIsSomethingToDelete()和deleteSomething()方法没有使用putInCache()使用的相同对象锁正确同步对缓存对象的访问

如果我将
putInCache()
声明为
synchronized
,该怎么办?这会使两种方法“更安全”吗?您需要在字段级别保护访问,这意味着访问这些字段的所有方法都需要在同一个锁对象上同步。简而言之,您还需要在checkFreeSpace()中添加一个同步块。谢谢您的回复。首先,
public
不是什么大问题,因为这两个方法只由同一类中的另一个方法调用。至于
有一些thingtodelete()
deleteSomething()
,我实际上没有这些方法。它们的逻辑包含在
checkFreeSpace
方法中,但如果我把所有代码都放在这里,那就太混乱了。让我们假设这些方法是正确同步的。对不起,我选择了错误的方法来提问。请看一看编辑后的版本。因此推测putInCache()也不是真正私有的(否则该类实际上如何使用)。然后,我认为该类是线程安全的,因为只有当线程持有putInCache()synchronized块建立的锁时,才能访问可变状态(在该代码中使用
AtomicLong