Почему в С# нет параллельных коллекций?

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

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

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

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

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

Ответ 1

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

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

Ответ 2

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

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

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

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

Ответ 3

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

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

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

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

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