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