У меня есть многопоточный код и один массив, к которому все потоки должны обращаться к нему, и только один может его изменить (добавить, удалить,..) или изменить объект в нем. Мне нужен безопасный способ, чтобы потоки обращались к нему. Я читал о синхронизации блокировки мьютекса, синхронизированного списка, copyonwritearraylist и volatile.
Будет много итераций, поэтому я не могу поставить синхронизацию вне цикла следующим образом:
synchronized (list) {
Iterator i = list.iterator();
//Must be in synchronized block
while (i.hasNext())
foo(i.next());
}
потому что я потеряю преимущество многопоточности. И размер моих списков может составить около 1000, поэтому я не могу заблокировать весь список, пока итерация на всех этих элементах
Я также прочитал о CopyOnWriteArrayList, который подходит для ситуаций, когда список используется для итерации, которая не должна быть изменена
Итак, какое наилучшее решение для использования в такой ситуации, как моя
CopyOnWriteArrayList
действительно может быть тем, что вы хотите. Это позволяет вам перебирать моментальный снимок списка, как он существовал в определенный момент времени. Возможно, он не идентичен списку, как сейчас, но вам это действительно нужно?
Подумайте об этом таким образом. Итерация потока по списку и поток, изменяющий список, могут чередовать их операции различными способами, ни одна из которых не является ошибкой. Одна из возможностей заключается в том, что итерационная нить может перебираться по всему списку до того, как будет запущен модифицирующий поток. Другая возможность заключается в том, что итерационный поток будет попадать наполовину через список до его изменения. Распространение изменений на все существующие итераторы было бы сложной и дорогостоящей операцией, и вам нужно было бы тщательно определить, что делает итератор, например, когда что-то вставлено ниже его текущей позиции. И вся эта сложность не сделала бы программу более правильной, потому что поведение было бы идентично CopyOnWriteArrayList
если бы потоки просто планировались несколько иначе.
Это шаблон, с которым вы часто сталкиваетесь в эффективных, высококонкурентных программах. Важно то, что поток работает с действительным моментальным снимком объекта, не обязательно текущей версией объекта, как это известно для какого-то другого потока.