Как добавить и удалить из HashMap для многих авторов и читателей (темы)? - PullRequest
0 голосов
/ 27 февраля 2020

Можно ли решить этот код без синхронизации ключевых слов?

Можем ли мы использовать ConcurrentHashMap или лучше HashMap с синхронизированным ключевым словом (для методов)?
Или лучше ConcurrentHashMap (для итерации) с синхронизированным ключевое слово (для методов)?

Это критический код раздела, поток чтения получает statisti c, и когда значение уменьшается (если значение равно нулю, удаляет statisti c, но поток параллельного модуля записи может инициировать значение ). Как правильно решить эту проблему?

     Statistic statistic = data.get(id);
        if (statistic != null) {
            statistic.dec();

            if (statistic.getValue() <= 0) {
                data.remove(id);
           }
public class Main {

    private static final Map<Long, Statistic> data = new ConcurrentHashMap<>();

    public static void main(String... args) throws IOException {
        new Thread(() -> todoRunInWriterThread(1L)).start();
        new Thread(() -> todoRunInReaderThread(1L)).start();

        System.in.read();
    }

    //Many writers write some statistics
    private static void todoRunInWriterThread(long id) { 
        Statistic statistic = data.get(id);
        if (statistic == null) {
            statistic = new Statistic();
            data.put(id, statistic);
        }

        statistic.inc();
    }

    //Many readers read statistic and decrement value, 
    //if statistic value is zero (remove statistic)
    private static void todoRunInReaderThread(long id) {
        Statistic statistic = data.get(id);
        if (statistic != null) {
            statistic.dec();

            if (statistic.getValue() <= 0) {
                data.remove(id);
            }
        }
    }

    public static class Statistic {
        private AtomicLong value = new AtomicLong(0);

        public long getValue() {
            return value.longValue();
        }

        public void inc() {
            value.incrementAndGet();
        }

        public void dec() {
            value.decrementAndGet();
        }
    }
}

1 Ответ

1 голос
/ 27 февраля 2020

Я считаю, что вы должны использовать ConcurrentHashMap. В большинстве случаев он имеет хорошую производительность, и ваш случай для потока записи (get ... check if null ... put) может быть решен с помощью ConcurrentHashMap # computeIfAbsent -> он будет обрабатывать все внутренние блокировки.

Также пожалуйста, сделайте небольшое исследование о том, как работает ConcurrentHashMap. это не просто использование синхронизированного ключевого слова для каждого метода. Здесь задействована блокировка чередования, которая действительно хороша для производительности

...