2011-12-13 2 views
0

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

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 < String, RouterTableEntry()). Какой самый разумный способ в Java сделать это?

+0

Зависит, действительно, так как есть возможность использовать 'ConcurrentHashMap', который является частью Java Concurrency: http://stackoverflow.com/questions/510632/whats-the-difference-between-concurrenthashmap-and-collections -синхронизированная карта и http://www.ibm.com/developerworks/java/library/j-jtp08223/ – birryree

ответ

3

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

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

1

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

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

1

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

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

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

1

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

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

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

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

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

1

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

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

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

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

Смежные вопросы