Несикронизированная карта LinkedHashMap приводит к утечкам памяти в многопоточной среде?

#java #multithreading

Вопрос:

Я задаюсь вопросом о следующих вещах

  1. Не происходит ли утечка памяти, даже если sycronized не реализован в get method ?
  2. Если происходит утечка памяти, в чем причина?

шаг 1: поместите ключ : «a» -gt; значение : «b»

шаг 2: поток 1 -gt; удалить(«a»), поток 2 -gt;gt; получить(«a») (происходит одновременно)

=gt; будет ли класс кэша по-прежнему ссылаться на «b»? разве «б» не может быть вечно собранным мусором?

 class Cache {  private Maplt;String, Stringgt; cache = new LinkedHashMaplt;gt;();   public synchronized void put(String key, String value) {  cache.put(key, value);  }   public synchronized void remove(String key) {  cache.remove(key);  }   public String get(String key) {  return cache.get(key);  }  }  

Комментарии:

1. Можете ли вы объяснить, почему вы думаете HashMap , что после вызова будет ссылка на b remove("a") ?

2. Похоже, что jvm должна знать, что «b» больше не упоминается в хэш-карте для сбора мусора. Я не уверен, потому get method что он не синхронизирован, но я беспокоюсь, что может возникнуть проблема со ссылкой.

3. Отсутствие синхронизации, как правило, вызывает гораздо более странные проблемы, чем простые утечки памяти. Это возможный результат, но, конечно, не гарантированный.

4. Для добавления новых элементов требуется обновление от нескольких до многих тысяч инструкций. Например, если карта определяет, что она слишком заполнена, она преобразует все элементы в новую карту с большим количеством ячеек. Даже обычное добавление или удаление одного элемента требует настройки самобалансирующихся деревьев, реализующих сегменты. Если синхронизация потоков отсутствует, поток чтения может предотвратить запись в середине, когда структура данных находится в несогласованном состоянии. Возвращаемые значения вполне могут быть ненужными. Может возникнуть исключение (например, NPE). Я не могу понять, как может произойти утечка памяти, но это не значит, что этого не произойдет.

5. @LouisWasserman Я думаю , что здесь существует языковой барьер, и он спрашивает конкретно о случае, когда запись синхронизируется, а чтение-нет, и может ли в таких ситуациях произойти утечка памяти. Я думаю, это домашнее задание.

Ответ №1:

Я сам нашел ответ, я записываю его, чтобы поделиться.

Приведенный ниже код является частью LinkedHashMap

 public V get(Object key) {  Nodelt;K,Vgt; e;  if ((e = getNode(hash(key), key)) == null)  return null;  if (accessOrder)  afterNodeAccess(e);  return e.value;  }   void afterNodeAccess(Nodelt;K,Vgt; e) { // move node to last  LinkedHashMap.Entrylt;K,Vgt; last;  if (accessOrder amp;amp; (last = tail) != e) {  LinkedHashMap.Entrylt;K,Vgt; p =  (LinkedHashMap.Entrylt;K,Vgt;)e, b = p.before, a = p.after;  p.after = null;  if (b == null)  head = a;  else  b.after = a;  if (a != null)  a.before = b;  else  last = b;  if (last == null)  head = p;  else {  p.before = last;  last.after = p;  }  tail = p;    modCount;  }  }  

В случае LinkedHashMap, если вы не используете synchronized, могут возникнуть проблемы, если вы не используете synchronized, поскольку опорные значения до и после изменяются при чтении. На самом деле, мне было интересно, есть ли проблема при чтении с различных типов карт, и я задавался вопросом, может ли возникнуть проблема утечки памяти при чтении в зависимости от реализации карты.