Collection.synchronizedMap против синхронизации отдельных методов в HashMap - PullRequest
4 голосов
/ 11 февраля 2010

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

По сути, в чем разница между следующими фрагментами кода

Class C {    
    Object o;

    public void foo() {
       synchronized(o) {
           // thread safe code here
       }
    }
}

и

Class C {
    Object o;

    public synchronized void foo() {

    }
}

Ответы [ 6 ]

3 голосов
/ 11 февраля 2010

Разница только одна:

Collections.synchronizedMap может использовать монитор, отличный от самого себя.

Использование синхронизированных методов аналогично использованию sychnchonized(this) -блоков, что означает, что обертка будет монитором и может быть заблокирована снаружи обертки.

Если вы не хотите, чтобы внешнее приложение блокировало ваш монитор, вам нужно его скрыть.

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

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

2 голосов
/ 11 февраля 2010

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

Сказав, что тоже не используйте, используйте ConcurrentHashMap.Он использует чередование блокировок, поэтому использовать его намного быстрее, чем любой другой подход (так как они одинаковы с точки зрения накладных расходов и конфликтов).Чередование блокировок позволяет независимо блокировать сегменты подложки.Это означает, что менее вероятно, что два потока запросят получение одной и той же блокировки.

1 голос
/ 11 февраля 2010

Не изобретайте велосипед и не используйте то, что предусмотрено API.

0 голосов
/ 15 февраля 2012

Если речь идет о безопасности потоков, используйте структуры данных пакета параллелизма. Использование класса-оболочки уменьшит все обращения к карте в последовательную очередь.

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

б) Рассмотрим сложные операции на карте. Использование обертки с одиночной блокировкой не поможет. Например. Вид операций «Посмотри, если есть, добавь». Синхронизация потоков снова станет проблемой.

0 голосов
/ 11 февраля 2010

Итак, почему вы спрашиваете? :) Вы действительно верите, что если класс помещен в пакет java.util, тогда происходит какое-то волшебство, и его java-код работает каким-то хитрым образом?

Это действительно просто оборачивает все методы синхронизированным блоком {} и ничего более.

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

UPD 2: как вы можете видеть из источников, они используют объект mutex в качестве монитора. Когда вы используете синхронизированный модификатор в сигнатуре метода (т.е. synchronized void doSmth()), текущий экземпляр вашего объекта (т.е. this) используется в качестве монитора. Два блока кода ниже одинаковы:

1

synchronized public void doSmth () {
   someLogic ();
   moreLogic ();
}

synchronized public static void doSmthStatic () {
   someStaticLogic ();
   moreStaticLogic ();
}

2

public void doSmth () {
   synchronized (this) {
      someLogic ();
      moreLogic ();
   }
}

public static void doSmthStatic () {
   synchronized (ClassName.class) {
      someStaticLogic ();
      moreStaticLogic ();
   }
}
0 голосов
/ 11 февраля 2010

Вы должны всегда украшать, а не смешивать все и все в один большой класс.

Всегда берите простую карту и украшайте ее коллекциями или используйте java.util.concurrent и используйте реальный замок, чтобы можно было атомарно проверить и обновить карту. Завтра вы можете захотеть изменить Hashtable на Treemap, и у вас возникнут проблемы, если вы застряли с хеш-таблицей.

...