Подобно тому, что было упомянуто другими, синхронизированные коллекции поточно-безопасны , но составные действия с этими коллекциями не гарантируют поточно-ориентированные по умолчанию.
Согласно JCIP, общие составные действия могут быть
- итерация
- навигация
- put-if-отсутствующий
- check-then-act
Блок синхронизированного кода 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
.Предположим, что текущий lastIndex
равен 10.
Тема A (deleteLast) -> удалить
Тема B (getLast) --------------------> get
Thread A remove
элемент перед операцией get
в Thread B. Таким образом, Thread B по-прежнему использует 10 в качестве lastIndex
для вызова list.get
метода, он приведетк сопутствующей проблеме.