Может ли получить, поместить и удалить элемент в HashMap без итерации, вызвав ConcurrentModificationException? - PullRequest
0 голосов
/ 07 сентября 2018

У меня есть статический hashMap, совместно используемый несколькими потоками. Я вообще не повторяю карту, а просто использую get, put, remove. Это безопасно от ConcurrentModificationException?

Метод выглядит так

private static Map<Long, Integer> TRACKER = new HashMap<Long,Integer>();
public static void track(Long tid, boolean b) {
        if (b) {
            if (TRACKER.containsKey(tid)) {
                TRACKER.put(tid, TRACKER.get(tid) + 1);
            } else {
                TRACKER.put(tid, 1);
            }
        } else {
            Integer n = TRACKER.get(tid);
            if (n != null) {
                n = n -1;
                if (n == 0) {
                    TRACKER.remove(tid);
                } else {
                    TRACKER.put(tid, n);
                }
            }
        }
    }

Ответы [ 2 ]

0 голосов
/ 07 сентября 2018

Это безопасно от ConcurrentModificationException?

Это безопасно от ConcurrentModificationException. Это исключение вызывается только методами, которые выполняют итерацию (в некотором смысле) карты или одного из ее видов с использованием обычного итератора или сплитератора.

Однако, поскольку HashMap не является потокобезопасным классом, если вы используете его из нескольких потоков без надлежащей внешней внешней синхронизации, могут произойти плохие вещи. К ним относятся (в порядке увеличения вредности)

  1. Метод size(), сообщающий о неверном значении.
  2. Записи загадочно исчезают, временно или навсегда.
  3. Возможные NPE и другие непроверенные исключения.
  4. Возможны бесконечные циклы из-за неудачной последовательности операций нескольких потоков, создающих цикл в цепочке хэшей.

Ваш пример кода небезопасен ... но вы не получите "быстрый сбой" ConcurrentModificationException. Вместо этого вы можете получить необъяснимые ошибки в «случайное» время, которые трудно воспроизвести.

0 голосов
/ 07 сентября 2018

Если несколько потоков выполняют операции get, put & remove на HashMap, без надлежащей синхронизации, некоторые плохие вещи, такие как size (), сообщают об отсутствующих / потерянных записях, неожиданных NPE ... даже бесконечные могут возникнуть петли.

HashMap документация говорит -

Обратите внимание, что эта реализация не синхронизирована. Если несколько потоков получить доступ к хэш-карте одновременно и, по крайней мере, к одному из потоков изменяет карту структурно, она должна быть синхронизирована извне. (A структурная модификация - это любая операция, которая добавляет или удаляет один или больше отображений; просто изменив значение, связанное с ключом, который экземпляр уже содержит не является структурной модификацией.) ...

Спасибо, Стивен.

...