Collection.synchronizedMap против синхронизации отдельных методов в HashMap

StackOverflow https://stackoverflow.com/questions/2242611

Вопрос

В чем разница между 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() {

    }
}
Это было полезно?

Решение

Есть только одно отличие:

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

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

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

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

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

Другие советы

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

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

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

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

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

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

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

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

УПД 2:как вы можете видеть в источниках, они используют объект «мьютекс» в качестве монитора.Когда вы используете модификатор синхронизации в сигнатуре метода (т.е. 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 ();
   }
}

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top