Collections.synchronizedList и синхронизированы

java collections synchronization

61820 просмотра

6 ответа

364 Репутация автора

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

Блок "synchronized (list) {}" действительно нужен здесь?

Автор: romsky Источник Размещён: 27.02.2012 04:08

Ответы (6)


21 плюса

263942 Репутация автора

Базовый код для метода добавления Collections.synchronizedList:

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

Так что в вашем примере не нужно добавлять синхронизацию.

Автор: assylias Размещён: 27.02.2012 04:15

94 плюса

4504 Репутация автора

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

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

List list = Collections.synchronizedList(new ArrayList());
...
synchronized(list) {
    Iterator i = list.iterator(); // Must be in synchronized block
    while (i.hasNext())
        foo(i.next());   
}
Автор: Sam Goldberg Размещён: 27.02.2012 04:16

28 плюса

381609 Репутация автора

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

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

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

Автор: NPE Размещён: 27.02.2012 04:17

16 плюса

165 Репутация автора

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

Автор: jpegjpg Размещён: 24.10.2012 12:20

7 плюса

71 Репутация автора

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

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

Автор: snan Размещён: 15.01.2013 04:37

1 плюс

5649 Репутация автора

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

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

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

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

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

Есть два способа , которые работают на той же коллекции , listчто обернутCollections.synchronizedList

public Object getLast(List<String> list){
    int lastIndex = list.size() - 1;
    return list.get(lastIndex);
}

public void deleteLast(List<String> list){
    int lastIndex = list.size() - 1;
    list.remove(lastIndex);
}

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

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

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

Автор: Gearon Размещён: 20.11.2017 01:42
Вопросы из категории :
32x32