Синхронизация вложенных карт и наборов (Java) - PullRequest
2 голосов
/ 04 мая 2011

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

Карта создается как таковая:

private final Map<Manageable, Map<String, Set<Manageable>>> manageableMap = 
        Collections.synchronizedMap(new HashMap<Manageable, Map<String, Set<Manageable>>>());

Это функция, которую я использую для добавления значений на карту:

private void put(Manageable key, Manageable value, String valueType) {
    synchronized (manageableMap) {
        Map<String, Set<Manageable>> setMap = manageableMap.get(key);
        if (setMap == null) {
            setMap = new HashMap<String, Set<Manageable>>();
            manageableMap.put(key, Collections.synchronizedMap(setMap));
        }

        synchronized (setMap) {
            Set<Manageable> set = setMap.get(valueType);
            if (set == null) {
                set = new HashSet<Manageable>();
                setMap.put(valueType, Collections.synchronizedSet(set));
            }

            synchronized (set) {
                set.add(value);
            }
        }
    }
}

Intellij IDEA предупреждает меня, что я синхронизируюсь с локальными переменными setMap и set.

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

Спасибо за помощь.

Ответы [ 3 ]

3 голосов
/ 04 мая 2011

Вам нужно синхронизироваться только на manageableMap. Только 1 поток одновременно может получить блокировку на manageableMap, поэтому, если поток получил блокировку на manageableMap, дальнейшая блокировка для set и setMap не требуется, так как только 1 поток (поток, который заблокировал manageableMap) может получить доступ к set и setMap .

1 голос
/ 04 мая 2011

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

1 голос
/ 04 мая 2011

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

В этом конкретном случае IDEA не может статически проверять, выполняет ли код то, что вам нужно, предупреждение - это просто некий «запах кода», предупреждающий вас о том, что эффект может быть не таким, как ожидалось.

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

...