Условия гонки при добавлении, а не чтении из списка <T>(или стека или очереди) - что происходит? - PullRequest
1 голос
/ 20 апреля 2011

Примечание: я задаю этот вопрос относительно структуры 3.5, поэтому я не включаю ни одну из более новых многопоточных конструкций в 4.0 (которую я все еще изучаю).

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

Допустим, у вас есть приложение с несколькими потоками, которые все генерируют объекты, причем каждый поток генерирует уникальный объект. Существует один экземпляр коллекции (List, Stack или Queue), который является хранилищем объектов после того, как они были созданы, и объекты эффективно неизменяемы после добавления в коллекцию.

Во время этого процесса единственной операцией в коллекции является добавление элементов. Там нет чтения, удаления или подсчета сделано. Неважно, какой порядок предметов в коллекции.

Вопрос в том, не существует ли блокировка вокруг коллекции, когда отдельные потоки пытаются добавить объекты, это действительно проблема?

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

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

Может ли кто-нибудь предоставить мне некоторую информацию, которая поможет положить этот аргумент в порядок? Мне особенно интересно услышать, что может доказать, что я не прав.

Ответы [ 3 ]

1 голос
/ 20 апреля 2011

Добавление элементов в List<T> (или стек и т. Д.) не поточно-ориентировано .

Это включает

  • Проверка достаточности внутреннего размера массива
  • Если нет, создайте новый массив, скопируйте все элементы
  • Установить элемент в массиве с индексом, равным длине List<T>

Ни один из вышеперечисленных процессов не является поточно-ориентированным , и в коде платформы .NET отсутствует синхронизация. Так что если вы не синхронизируете, я гарантирую ваш список будет поврежден.

0 голосов
/ 20 апреля 2011

Вы в основном правы, хотя некоторые из более простых структур, таких как стек или очередь, могут быть "случайно" поточно-ориентированными. У вас нет гарантии того, как реализованы «внутренности» любой коллекции. Например, список поддерживается массивом. Если вы добавите новый элемент, который заставит его увеличивать массив, он (может) скопирует все значения в новый больший массив. Это вероятно потокобезопасный в своей реализации, но, поскольку это не потокобезопасный объект, нет контракта на его безопасность потока.

0 голосов
/ 20 апреля 2011

Добавление элементов в список включает чтение и запись в память, поэтому, если нет синхронизации, есть гонка.

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