Синхронизированная карта или синхронизированные методы - PullRequest
1 голос
/ 14 декабря 2011

У меня есть следующий класс для таблицы маршрутизатора с синхронизированными методами:

public class RouterTable {

    private String tableForRouter;
    private Map<String,RouterTableEntry> table;

    public RouterTable(String router){

        tableForRouter = router;
        table = new HashMap<String,RouterTableEntry>();
    }

    public String owner(){

        return tableForRouter;
    }

    public synchronized void add(String network, String ipAddress, int distance){

        table.put(network, new RouterTableEntry(ipAddress, distance));
    }

    public synchronized boolean exists(String network){

        return table.containsKey(network);
    }
}

Несколько потоков будут читать и записывать в HashMap.Мне было интересно, будет ли лучше удалить синхронизированные методы и просто использовать Collections.synchronizedMap (новый HashMap

Ответы [ 5 ]

4 голосов
/ 14 декабря 2011

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

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

1 голос
/ 14 декабря 2011

Текущий общий стиль имеет тенденцию отдавать предпочтение синхронизированным коллекциям по сравнению с явной синхронизированной квалификацией методов, которые обращаются к ним.Тем не менее, это не обязательно, и ваше решение должно зависеть от того, как вы используете этот код / ​​будете использовать этот код в будущем.

Вопросы для рассмотрения:

(a) Есливаша карта будет использоваться кодом, который находится за пределами RouterTable, тогда вам нужно использовать SynchronizedMap.

(b) OTOH, если вы собираетесь добавить некоторые дополнительные поля к RouterTable и их значения должны соответствовать значениям на карте (другими словами: вы хотите, чтобы изменения на карте и в дополнительных полях происходили в одном атомном кванте), тогда вам нужно использовать метод synchrnoized.

1 голос
/ 14 декабря 2011

Синхронизация карты не позволит пользователям вашего класса выполнять значимую синхронизацию.

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

С синхронизированными методами, как вы показываете, они могут блокировать ваш класс, пока они не будут завершены с блоком вызовов методов.

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

Добавление собственной синхронизации - вот что не так с HashTable.

1 голос
/ 14 декабря 2011

Лучше всего использовать java.util.concurrent.ConcurrentHashMap, который спроектирован с нуля для одновременного доступа (чтение и запись).

Использование синхронизации, как вы делаете, работает, но показывает высокий уровень конкуренциии, следовательно, не оптимальная производительность.Коллекция, полученная с помощью Collections.synchronizedMap (), будет делать то же самое (она только оборачивает стандартную коллекцию синхронизированными методами).

ConcurrentHashMap, напротив, использует различные методы для обеспечения безопасности потоков и обеспечения хорошего параллелизма;например, он имеет (по умолчанию) 16 областей, каждая из которых защищена определенной блокировкой, так что до 16 потоков могут использовать ее одновременно.

1 голос
/ 14 декабря 2011

В отсутствие строгих требований к отношениям «до события» и корректности на момент времени разумной вещью, которую нужно делать в современной java, обычно является просто использование ConcurrentMap .

В противном случае, да, использование Collections#synchronizedMap является одновременно более безопасным и, вероятно, более производительным (потому что вы не вложите какой-либо третичный код, который не требует синхронизации), чем ручная синхронизация всего себя.

...