Что это значит, когда мы говорим, что ArrayList не синхронизирован? - PullRequest
15 голосов
/ 02 августа 2011

Что это значит, когда мы говорим, что ArrayList не синхронизирован?

Означает ли это, что если мы объявим ArrayList в области видимости объекта, несколько потоков, обращающихся к объектам, получат возможность изменить список?

Ответы [ 6 ]

11 голосов
/ 02 августа 2011

Что это значит, когда мы говорим, что ArrayList не синхронизирован?

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

Дальнейшее чтение:

Означает ли это, что если мы объявляем ArrayList в области видимости объекта, несколько потоков, обращающихся к объектам, имеют возможность изменять список?

Даже если бы это было поточно-ориентированным, несколько потоков могли бы изменить список.

Разница в том, что если это не потокобезопасно и несколько потоков получают доступ к списку, все ставки отключены. Сказать, что класс не является потокобезопасным, - это то же самое, что добавить «Если к нему обращаются из одного потока за раз, этот метод работает следующим образом…» перед каждым описанием метода.

3 голосов
/ 02 августа 2011

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

С ArrayList (или коллекциями в целом) есть две проблемы параллелизма.

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

Синхронизация метода может быть обеспечена путем переноса ArrayList следующим образом:

List list = Collections.synchronizedList(new ArrayList());

Пример: предположим, что два потока одновременно пытаются выполнить следующее:

list.add(0, "test");

Если у вас есть синхронизированный список, вам гарантировано, что список послесловий начинается с двух «тестовых» записей. Если список не синхронизирован, вы можете получить список только с одной «тестовой» записью ... или другими неожиданными результатами.

Второй , есть синхронизация экземпляров. Здесь мы не только предотвращаем одновременные вызовы методов, но и следим за тем, чтобы только один поток имел доступ к объекту списка на время. Это важно, если у вас есть кусочки логики, которые требуют, чтобы список оставался в неизменном состоянии до тех пор, пока логика не будет выполнена. Например, перебирая списки. Вы не хотите, чтобы другие потоки добавляли элементы во время итерации по списку.

Этот тип синхронизации выполняется путем обертывания вашей логики в синхронизированный блок:

synchronized(list) {
      for (Object o:list) {
         ...
      }
}
1 голос
/ 02 августа 2011

Это означает, что экземпляры ArrayList не гарантированно безопасны для потоков. Обычно это включает как чтение, так и запись. Если вы делаете это без внешней синхронизации, вы можете оставить объект в состояниях stange и получить несколько сложностей для отладки.

1 голос
/ 02 августа 2011

Означает ли это, что если мы объявим ArrayList в области видимости объекта, несколько потоков, получающих доступ к объектам, смогут изменить список?

Да. Если одновременно работают несколько потоков, это может привести к неожиданному поведению

0 голосов
/ 14 мая 2019

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

Если вы работаете в однопоточной среде (или список ограничен потоком и никогда не разделяется), используйте ArrayList.Если вы работаете с несколькими потоками, которые совместно используют одну и ту же коллекцию, либо используйте Vector, либо используйте ArrayList, но синхронизируйте другим способом (например, вручную или через оболочку).

0 голосов
/ 02 августа 2011

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

По умолчанию ArrayList не синхронизируется, этого можно добиться с помощью синхронизированного ключевого слова

ArrayList al=new ArrayList();

Collections.synchronized(al);
...