Почему мы здесь, в частности, говорим, что ArrayList не является потокобезопасным? - PullRequest
0 голосов
/ 07 апреля 2020

Описание: если мы используем одну и ту же ссылку на объект среди нескольких потоков, ни один объект не является поточно-ориентированным. Аналогично, если какая-либо ссылка на коллекцию является общей для нескольких потоков, эта коллекция не является потоком, поскольку другие потоки могут получить к ней доступ. Итак, почему мы здесь специально говорим, что ArrayList не является потокобезопасным? А как насчет других коллекций?

Ответы [ 3 ]

2 голосов
/ 07 апреля 2020

Вы неправильно понимаете значение слова "потокобезопасный".

Когда мы говорим "класс X является потокобезопасным", мы не говорим, что вы не нужно беспокоиться о поточной безопасности программы, которая его использует. Если вы создаете программу с использованием ничего, кроме поточно-ориентированных объектов, это не гарантирует, что ваша программа будет поточно-ориентированной.

Так что же гарантирует это гарантирует?

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

Если список «потокобезопасен», то вы можете быть уверены, что поток C получит одно из трех возможных значений:

  • Значение, которое записал поток A,
  • Значение, которое записал поток B,
  • Значение, которое хранилось по этому индексу до записи потока A или потока B.

Если список не потокобезопасный, тогда может произойти любая из тех же трех вещей, но могут произойти и другие вещи:

  • Поток C может получить значение, которого никогда не было в списке,
  • В будущем список может работать некорректно для потока C, даже если другой поток не будет его использовать,
  • Программа может обработать sh,
  • et c. (Я не знаю, сколько других странных вещей могло бы произойти.)

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

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

1 голос
/ 07 апреля 2020

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

CopyOnWriteArrayList, например, является поточно-ориентированной реализацией List.

0 голосов
/ 07 апреля 2020

ArrayList несинхронизирован в реализации. Когда объект не синхронизирован, это означает, что он не заблокирован во время структурного изменения. A structural modification is any operation that adds or deletes one or more elements, or explicitly resizes the backing array; merely setting the value of an element is not a structural modification. То, что вы имеете в виду, - это массив, к которому элементы добавляются или удаляются, и который может быть изменен; это отличается от того, что его значение установлено.

Ссылка относится к указателю вопрос о начале массива, но о количестве элементов, о которых идет речь, и наличии несинхронизированного объекта, модифицируемого в смысле элементов, в то время как элементы перебираются другим потоком, целостность элементов в списке трудно гарантировать. Я надеюсь, что смог передать сообщение просто.

Более подробную информацию можно найти здесь в Oracle: Список массивов и ConcurrentModificationException

ArrayList :

Обратите внимание, что эта реализация не синхронизирована. Если несколько потоков обращаются к экземпляру ArrayList одновременно, и хотя бы один из потоков структурно изменяет список, он должен быть синхронизирован извне. (Структурная модификация - это любая операция, которая добавляет или удаляет один или несколько элементов или явно изменяет размер базового массива; просто установка значения элемента не является структурной модификацией.) Обычно это выполняется путем синхронизации с некоторым объектом, который естественным образом инкапсулирует список. Если такого объекта не существует, список следует «обернуть» с помощью метода Collections.synchronizedList.

ConcurrentModificationException:

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

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