Почему в C # нет одновременных коллекций? - PullRequest
15 голосов
/ 22 декабря 2009

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

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

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

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

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

Ответы [ 3 ]

28 голосов
/ 22 декабря 2009

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

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

19 голосов
/ 22 декабря 2009

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

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

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

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

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

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

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

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

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

...