Потокобезопасность Списка C# <T> для читателей

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

В этой статье http://msdn.microsoft.com/en-us/library/6sh2ey19.aspx MS описывает проблему потокобезопасности следующим образом:

Общедоступные помехи (Совместно использованный в Visual Basic) члены этого типа ориентированы на многопотоковое исполнение. Любые члены экземпляра, как гарантируют, не будут ориентированы на многопотоковое исполнение.

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

"Перечисление через набор является внутренне не ориентированной на многопотоковое исполнение процедурой". Оператор - то, что волнует меня.

Это означает, что это ориентировано на многопотоковое исполнение для читателей только сценарий, но, пока Вы не используете перечисление?

Или действительно ли это безопасно для моего сценария?


Спасибо за ответы. Почему я должен использовать AsReadOnly вообще, если он будет работать с или без него?

12
задан Kev 15 September 2011 в 13:01
поделиться

3 ответа

Они означают, что если вы перечисляете коллекцию, в то время как другой поток (или ваш собственный) изменяет ее, у вас будут проблемы.

Пока вы вообще не меняете коллекцию и не разделяете IEnumerator между потоками, у вас не должно возникнуть никаких проблем.

8
ответ дан 2 December 2019 в 21:42
поделиться

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

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

private static List<T> shared_list;

private static ReadOnlyCollection<T> _data;
public static IEnumerable<T> Data
{
    get
    {
        return _data ?? (_data = shared_list.AsReadOnly());
    }
}

==== EDIT ====

Эта версия кэширует ссылку ReadOnlyCollection для более быстрого поиска в будущем.

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

3
ответ дан 2 December 2019 в 21:42
поделиться

Означает ли это, что это потокобезопасный для сценария только для читателей, но до тех пор. пока вы не используете перечисление? Или это безопасно для моего сценария?

Зависит полностью от того, когда вы пишете в коллекцию. Это не может совпадать с чтением (перечислением) без какой-либо схемы блокировки.

Так что если вы заполняете коллекцию один раз и затем только перебираете ее, вы в безопасности. Но когда один поток изменяет список (добавляет или удаляет элементы), вам понадобится, например, ReaderWriterLockSlim.

Когда вы изменяете состояние хранимого элемента, потокобезопасность связана с этим элементом (а не со списком).

1
ответ дан 2 December 2019 в 21:42
поделиться
Другие вопросы по тегам:

Похожие вопросы: