Синхронизировано или нет, ArrayList всегда может быть изменен несколькими потоками. Синхронизация - это предотвращение одновременного доступа .
С ArrayList (или коллекциями в целом) есть две проблемы параллелизма.
Первый , есть метод синхронизации. Это означает, что все вызовы методов экземпляра ArrayList синхронизированы. Поэтому за один раз всегда выполняется только один метод. Все остальные вызовы методов, которые происходят, пока первый метод все еще вычисляет, помещаются в очередь до завершения работающего метода.
Синхронизация метода может быть обеспечена путем переноса ArrayList следующим образом:
List list = Collections.synchronizedList(new ArrayList());
Пример: предположим, что два потока одновременно пытаются выполнить следующее:
list.add(0, "test");
Если у вас есть синхронизированный список, вам гарантировано, что список послесловий начинается с двух «тестовых» записей. Если список не синхронизирован, вы можете получить список только с одной «тестовой» записью ... или другими неожиданными результатами.
Второй , есть синхронизация экземпляров. Здесь мы не только предотвращаем одновременные вызовы методов, но и следим за тем, чтобы только один поток имел доступ к объекту списка на время. Это важно, если у вас есть кусочки логики, которые требуют, чтобы список оставался в неизменном состоянии до тех пор, пока логика не будет выполнена. Например, перебирая списки. Вы не хотите, чтобы другие потоки добавляли элементы во время итерации по списку.
Этот тип синхронизации выполняется путем обертывания вашей логики в синхронизированный блок:
synchronized(list) {
for (Object o:list) {
...
}
}