Почему в C# нет одновременных коллекций?

Я пытаюсь получить обзор теории безопасности потоков в коллекциях C#.

Почему нет параллельных коллекций, как в Java? ( Java документы). Некоторые коллекции выглядят поточно-безопасными, но мне не ясно, какова позиция, например, в отношении:

  • сложные операции,
  • безопасность использования итераторов,
  • операции записи

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

Я надеюсь, что сообщество может помочь.

3 ответа

Решение

До сих пор в.NET была относительно параллельная поддержка "низкого уровня", но в.NET 4.0 вводится System.Collections.Concurrent пространство имен, которое содержит различные коллекции, которые безопасны и полезны.

Ответ Эндрю совершенно верен с точки зрения того, как обращаться с коллекциями до.NET 4.0, конечно, - и для большинства случаев я просто блокировал бы при доступе к "нормальной" общей коллекции. Однако одновременные коллекции упрощают использование очереди производителя / потребителя и т. Д.

C# предлагает несколько способов работы с коллекциями в нескольких потоках. Для хорошего написания этих методов я бы порекомендовал вам начать с коллекций и синхронизации (Thread Safety):

По умолчанию классы Collections, как правило, не являются потокобезопасными. Несколько читателей могут прочитать сборник с уверенностью; однако любая модификация коллекции приводит к неопределенным результатам для всех потоков, которые обращаются к коллекции, включая потоки чтения.

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

  • Создайте потокобезопасную оболочку, используя метод Synchronized, и обращайтесь к коллекции исключительно через эту оболочку.
  • Если у класса нет метода Synchronized, производный от класса и реализуйте метод Synchronized, используя свойство SyncRoot.
  • Используйте механизм блокировки, например оператор блокировки в C# (SyncLock в Visual Basic), в свойстве SyncRoot при доступе к коллекции.

Как отметил Джон Скит, в пространстве имен System.Collections.Concurrent в.NET 4 теперь есть "поточно-ориентированные" коллекции.

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

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

Например, предположим, что у пользователя есть Потокобезопасный словарь - если требуется вставить только в том случае, если Ключ не существует, он сначала запросит коллекцию, чтобы узнать, существует ли Ключ, затем можно выполнить вставку, если ключ не существует. Эти две операции не являются поточно-ориентированными, хотя между запросом ContainsKey и операцией Add другой поток мог бы выполнить вставку этого ключа, чтобы возникло состояние состязания.

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

Другие вопросы по тегам