Коллекции. Синхронизированный список и синхронизация

List list = Collections.synchronizedList(new ArrayList()); synchronized (list) { list.add("message"); } 

Является ли блок “synchronized (list) {}” действительно нужен здесь?

Вам не нужно синхронизировать, как вы помещаете в свой пример. ОДНАКО, очень важно, вам нужно синхронизировать этот список, когда вы его повторяете (как указано в Javadoc):

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

 List list = Collections.synchronizedList(new ArrayList()); ... synchronized(list) { Iterator i = list.iterator(); // Must be in synchronized block while (i.hasNext()) foo(i.next()); } 

Это зависит от точного содержимого synchronized блока:

  1. Если блок выполняет одиночную, атомную операцию в списке (как в вашем примере), synchronized избыток.

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

Основной код для метода Collections.synchronizedList add:

 public void add(int index, E element) { synchronized (mutex) {list.add(index, element);} } 

Поэтому в вашем примере не требуется добавлять синхронизацию.

Также важно отметить, что любые методы, которые используют iteratorы, например Collections.sort (), также должны быть инкапсулированы внутри синхронизированного блока.

Прочтите этот документ Oracle

В нем говорится: «Обязательно, чтобы пользователь вручную синхронизировал в возвращенном списке при повторении его»,

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

Согласно JCIP, общие действия соединения могут быть

  • итерация
  • навигация
  • пут-если-отсутствует
  • проверить-то-акт

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

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

Существует два метода, которые работают в том же list коллекций, который завершен Collections.synchronizedList

 public Object getLast(List list){ int lastIndex = list.size() - 1; return list.get(lastIndex); } public void deleteLast(List list){ int lastIndex = list.size() - 1; list.remove(lastIndex); } 

Если методы getLast и deleteLast вызываются одновременно двумя разными streamами, ниже могут происходить чередование, и getLast будет getLast ArrayIndexOutOfBoundsException . Предположим, что текущий lastIndex равен 10.

Тема A (deleteLast) -> удалить
Тема B (getLast) ——————–> get

Нить A remove элемент перед операцией get в streamе B. Таким образом, list.get B по-прежнему использует 10 в качестве метода lastIndex для вызова list.get , это приведет к одновременной проблеме.

  • Как защитить ресурсы, которые могут использоваться в многопоточной или асинхронной среде?
  • Как подождать, пока все горуты не закончатся, не используя время.
  • Почему не логично синхронизировать логику?
  • Статический и нестатический объект блокировки в синхронизированном блоке
  • Как @synchronized блокировка / разблокировка в Objective-C?
  • синхронизированный блок для объекта Integer
  • Как сделать блокировку с несколькими чтениями / одиночной записью из более простых примитивов синхронизации?
  • Как использовать свойство CancellationToken?
  • Явная блокировка Java
  • Чтение и запись C ++ int Atomic?
  • Как сделать мой ArrayList streamобезопасным? Другой подход к проблеме в Java?
  • Interesting Posts

    Spring Boot – как настроить порт

    Папка продолжает меняться обратно в режим «только для чтения». Какая настройка разрешений вызывает это в Windows?

    Список стандартных длин для полей базы данных

    Почему я получаю «алгоритм не сходился» и «устанавливал prob численно 0 или 1» предупреждения с помощью glm?

    dplyr :: mutate добавить несколько значений

    Как удалить конечные и ведущие пробелы для пользовательского ввода в пакетном файле?

    Как зашифровать и дешифровать файл в Android?

    Ошибка Omniauth Facebook – Faraday :: Ошибка :: ConnectionFailed

    objective-C Разница между установкой нуля и выпуском

    Закрытие приложения Excel с помощью VBA

    Использование переменных в именах свойств в LESS (динамические свойства / интерполяция свойств)

    как действительно работает метод обещания jquery?

    Как создать заводские файлы восстановления для ноутбука Dell с Windows 8?

    Вариадические рекурсивные macros препроцессора – возможно ли это?

    Печать двумерного массива в спиральном порядке

    Давайте будем гением компьютера.