Обязаны ли одновременные классы, предоставляемые JDK, использовать собственную синхронизацию своего экземпляра для синхронизации? - PullRequest
3 голосов
/ 15 мая 2011

JDK предоставляет набор потоковобезопасных классов, таких как ConcurrentHashMap, ConcurrentLinkedQueue и AtomicInteger.

Требуется ли синхронизация этих классов на this для реализации их поточно-ориентированного поведения?

При условии, что мы это сделаем, мы можем реализовать наши собственные синхронизированные операции над этими объектами и смешать их со встроенными?

Другими словами, это безопасно делать:

ConcurrentMap<Integer, Account> accounts 
    = new ConcurrentHashMap<Integer, Account>();

// Add an account atomically
synchronized(accounts) {
    if (!accounts.containsKey(id)) {
        Account account = new Account();
        accounts.put(id, account);
    }
}

И в другом потоке

// Access the object expecting it to synchronize(this){…} internally
accounts.get(id);

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

1 Ответ

6 голосов
/ 15 мая 2011

Требуется ли синхронизировать эти классы для реализации их поточно-ориентированного поведения.

Нет, и не только, различные инструменты проверки кода предупредят вас, если вы попробуетеиспользовать блокировку объекта.

В случае описанного выше метода put обратите внимание на javadoc :

Хеш-таблицу, поддерживающую полный параллелизм получения и настраиваемый ожидаемый параллелизм для обновлений.Этот класс подчиняется той же функциональной спецификации, что и Hashtable, и включает версии методов, соответствующие каждому методу Hashtable.Однако, несмотря на то, что все операции являются поточно-ориентированными, операции извлечения не влекут за собой блокировку, и нет никакой поддержки для блокировки всей таблицы таким образом, чтобы предотвратить любой доступ.Этот класс полностью совместим с Hashtable в программах, которые полагаются на безопасность потоков, но не на детали синхронизации.

Это означает, что параметры являются потокобезопасными, и нет способа сделать то, что выПытаюсь сделать выше (заблокировать всю таблицу).Кроме того, для операций, которые вы используете (put и get), ни одна из них не потребует такой блокировки.

Мне особенно нравится эта цитата из javadoc из метода values ​​():

Итератор представления является «слабо согласованным» итератором, который никогда не вызовет исключение ConcurrentModificationException и гарантирует прохождение элементов в том виде, в каком они существовали при создании итератора, и может (но не гарантируется) отражать любые изменения, следующие после построения.*

Итак, если вы используете этот метод, вы получите разумный список: он будет содержать данные на момент запроса и может иметь или не иметь более поздних обновлений.Гарантия того, что вам не придется беспокоиться о ConcurrentModificationExceptions, огромна: вы можете написать простой код без синхронизированного блока, показанного выше, и знать, что все будет просто работать.

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