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は、1 秒あたり約 139 スレッドによって呼び出されます。これら 2 つのメソッドが と の両方cacheで同期することを確認できますFREESPACEか? また、checkFreeSpace()マルチスレッドセーフですか。つまり、一度にこのメソッドの呼び出しが 1 つだけであることを確認できますか? このコードの「マルチスレッドの安全性」を改善できますか?

4

2 に答える 2

3

質問に完全に回答するには、thereIsSomethingToDelete()メソッドとdeleteSomething()メソッドの実装を示す必要があります。

checkFreeSpaceはパブリックメソッドであり(本当に必要ですか?)、同期されていない場合、putInCache()メソッドの同期ブロックの実行中に別のスレッドによって呼び出される可能性があります。checkFreeSpaceメソッドは空き領域の量を増やすことしかできず、減らすことはできないように見えるため、これ自体では何も壊れない可能性があります。

より深刻なのは(そしてコードサンプルではこれを判断できない)、thereIsSomethingToDelete()メソッドとdeleteSomething()メソッドが、によって使用されるのと同じオブジェクトロックを使用して、キャッシュオブジェクトへのアクセスを適切に同期しない場合です。 putInCache()。

于 2009-11-27T11:48:01.963 に答える
2

通常、アクセスを直接制御したいフィールドを同期することはありません。アクセスを同期するフィールドは、スレッド セーフと見なされるように、(同じオブジェクトの) 同期されたブロック内からのみアクセスする必要があります。ですでにこれを行っていますputInCache()。したがって、checkFreeSpace()非同期方式で共有状態にアクセスするため、スレッド セーフではありません。

于 2009-11-27T11:21:13.090 に答える