Синхронизация на двух или более объектах (Java) - PullRequest
2 голосов
/ 27 ноября 2009

У меня есть код, подобный следующему:

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() безопасна ли многопоточность, т. Е. Могу ли я быть уверен, что за один раз будет вызываться только один метод? Можно ли улучшить «многопоточность» этого кода?

Ответы [ 2 ]

3 голосов
/ 27 ноября 2009

Чтобы получить полный ответ на ваш вопрос, вам необходимо показать реализации методов thereIsSomethingToDelete () и deleteSomething ().

Учитывая, что checkFreeSpace является публичным методом (действительно ли он должен быть?) И не синхронизирован, возможно, он может быть вызван другим потоком во время выполнения синхронизированного блока в методе putInCache (). Само по себе это может ничего не сломать, так как кажется, что метод checkFreeSpace может только увеличить объем свободного пространства, но не уменьшить его.

Что может быть более серьезным (а пример кода не позволяет нам это определить), так это если методы thereIsSomethingToDelete () и deleteSomething () не синхронизируют свой доступ к объекту кэша должным образом, используя одну и ту же блокировку объекта как используется putInCache ().

2 голосов
/ 27 ноября 2009

Обычно вы не синхронизируете поля, доступ к которым вы хотите напрямую контролировать. Поля, к которым вы хотите синхронизировать доступ, должны быть доступны только из синхронизированных блоков (в том же объекте), чтобы считаться потокобезопасными. Вы уже делаете это в putInCache(). Следовательно, поскольку checkFreeSpace() обращается к общему состоянию несинхронизированным образом, это не безопасно для потоков.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...