.NET CLR - синхронизация ссылок на объекты - PullRequest
2 голосов
/ 19 августа 2011

В многопоточном приложении .NET

Предположим, что первый поток записывает в список. Второй поток очищает все элементы в нем. А третий поток считывает из списка.

Что происходитесли второй и третий потоки обращаются к одному и тому же объекту списка в одно и то же время на уровне CLR.Я не имею в виду объекты синхронизации .NET и механизм блокировки.

Я имею в виду, когда CLR обращается к элементам списка из ссылки (по 3-му потоку)), что произойдет, если список, на который указывает изменение ссылки (по 2-му потоку)?

Ответы [ 3 ]

2 голосов
/ 19 августа 2011

Плохие вещи.

Открытые статические (Shared в Visual Basic) члены этого типа являются поточно-ориентированными. Любые члены экземпляра не гарантируют поточно-ориентированность.

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

0 голосов
/ 19 августа 2011

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

//c#
List<object> myList...

//at reading thread
if (myList.Count > 0)
{
    object item = myList[0];//get the item at the first index of the collection.
}

//at writing thread
myList.Clear();

Поток записи обновляет список одновременно с тем, что поток чтения читает из списка, поэтому предположим, что выполнение было следующим:Поток читателя проверяет, есть ли элементы в коллекции, и обнаруживает, что в нем есть какие-то элементы ".Count > 0 true", поэтому он продолжает работу, но до достижения следующей строки переключение контекста потока приостанавливает поток чтения, переключаясь на поток записи, поэтому он выполняет свой код myList.Clear();, после чего контекст потока переключается обратно на поток чтения, чтобы продолжить выполнение, поэтому он пытается получить myList[0], ноколлекция была пустой в тот момент потоком записи, поэтому он завершится ошибкой с исключением IndexOutOfRange ..

Другой сценарий: если поток чтения, где выполняется итерация, создает коллекцию с использованием foreach, а поток записи простоизменяет коллекцию, «добавляя / удаляя» некоторые элементы, она снова генерирует исключение из-за изменения коллекции во время зацикливанияC # или использование Monitor класса. Однако, если вы используете 4.0, вы можете отключить использование ConcurrentCollection вместо обычных списков - это потокобезопасные коллекции.

0 голосов
/ 19 августа 2011

взрывается.InvalidOperationException выбрасывается, так как перечисление изменилось.

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