Какие методы карты должны быть синхронизированы для безопасности потока? - PullRequest
0 голосов
/ 20 февраля 2019

У меня есть класс, который содержит карту, и эта карта может быть доступна одновременно из нескольких потоков.

Я создаю свой класс следующим образом:

@Autowired
public Scheduler() {
    this.scheduledRunnables = Collections.synchronizedSortedMap(new TreeMap<Integer, Runnable>());
}

Итак, согласно документация , чтобы убедиться, что это работает правильно, я должен следовать этим рекомендациям:

Возвращает синхронизированную (поточно-ориентированную) отсортированную карту, поддерживаемую указанной отсортированной картой.Чтобы гарантировать последовательный доступ, очень важно, чтобы весь доступ к отсортированной по карте карте осуществлялся через возвращенную отсортированную карту (или ее виды).Крайне важно, чтобы пользователь вручную синхронизировался на возвращенной отсортированной карте при переборе любого из своих представлений коллекции или представлений коллекций любого из его представлений subMap, headMap или tailMap.

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

Я обращаюсь к этой карте двумя разными способами.

Доступ к наименьшемузначение ключа

Таким образом, я уверен, что на 99% я должен использовать синхронизированный блок, как это показано в документации при доступе к итератору.

public int getNextAvailableExecutionOrder() {
    synchronized (scheduledRunnables) {
        if (scheduledRunnables != null && scheduledRunnables.size() > 0) {
            return scheduledRunnables.keySet().stream().min(Comparator.comparing(Integer::valueOf)).get() + 1;
        }
        return Ordered.HIGHEST_PRECEDENCE + 1;
    }
}

Добавление новых runnables

В этом я немного не уверен.Доступ к итератору карт возможен здесь, или я могу безопасно добавлять в него новые элементы без синхронизированного блока?

protected void scheduledNewTask(final int order, final Runnable task) {
    LOG.info("Added new scheduled task {} with order {}", taskName, order);
    synchronized (scheduledRunnables) {
        scheduledRunnables.put(order, task);
    }
}

Редактировать

Выше моетекущая реализация, но, похоже, она не работает так, как я хочу:

2019-02-20 08:33:39.080  INFO 32082 --- [       Thread-6] s.i.s.a.gatemaster.SchedulingSupport     : Added new scheduled task Log upload with order -2147483648
2019-02-20 08:33:39.838  INFO 32082 --- [tHubReceiveTask] s.i.s.a.gatemaster.SchedulingSupport     : Added new scheduled task Firmware update (1.9.1) with order -2147483648

1 Ответ

0 голосов
/ 20 февраля 2019

Если это то, что вы опубликовали, это только два случая, когда вы обращаетесь к карте или манипулируете ею, вам не нужно оборачивать карту синхронизированной оболочкой с Collections.synchronizedSortedMap , потому что вы синхронизировали вседоступ к карте вручную, поэтому вам не нужна оболочка.

На ваш вопрос, если вы хотите использовать Collections.synchronizedSortedMap .Во втором доступе, когда вы помещаете что-то на карту, вам не нужно синхронизироваться вручную, потому что метод put уже синхронизирован оболочкой synchronizedSortedMap.Вы правильно синхронизировали доступ к карте в методе getNextAvailableExecutionOrder , потому что действительно итерируете потоковую карту, и вам нужно вручную синхронизировать это, как упомянуто в javadoc.

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