Lock free & Thread-Safe IList <T> для .NET
Существует ли блокирующая и потокобезопасная структура данных, которая реализует IList?
Естественно, без блокировки я имею в виду реализацию, которая не использует блокирующие примитивы в .NET, а использует блокированные операции/атомные операции для обеспечения безопасности потоков...
Существует не один, по-видимому, в параллельных структурах данных...
Кто-нибудь видел, как кто-то плавает?
Я видел Java-версию, реализованную в amino-cbbs, называемую LockFreeVector, но пока ничего для .NET.
Любые идеи?
Ответы
Ответ 1
Ну, я не мог найти такой класс нигде; поэтому Я дал ему снимок.
Исходный код для моего класса ConcurrentList<T>
доступен на GitHub.
Он блокируется, потокобезопасен (я думаю, на основе моих модульных тестов) и реализует IList<T>
.
Он не поддерживает Insert
, RemoveAt
/Remove
или Clear
.
Мне было приятно узнать, что моя реализация (которую я придумал самостоятельно) очень похожа на мою структуру данных опубликованную некоторыми уважаемыми умами в мире программного обеспечения.
Для довольно краткого обсуждения самой реализации см. мое последнее сообщение в блоге об этом.
В настоящий момент он не документируется вообще, что является довольно плохим, учитывая, насколько "сложным" является некоторый код: (
И, во что бы то ни стало, разорвите меня на новый, если вы посмотрите и найдете ошибки или другие проблемы.
В любом случае, это может стоить вашего времени, чтобы проверить это. Если да, дайте мне знать, что вы думаете.
Ответ 2
ConcurrentList, реализующий IList, может отсутствовать в пространстве имен Collections.Concurrent из-за целых Parallel.For
и Parallel.ForEach
методов класса. Можно сказать, что они могут использоваться для обработки любого списка как Concurrent, чтобы быстро перечислить список и выполнить действия над его элементами.
Возможно, не предоставив ConcurrentList
, они имели в виду или думали, что если Parralel.For не сможет помочь, вам потребуется использовать не IList, а какой-то другой вид коллекции, например, стек или очередь или даже Bag или даже Dictionary
Я бы согласился с этим дизайном, потому что необходимость иметь дело с индексируемой коллекцией в условиях многопоточности звучит как очень склонный к ошибкам и плохой дизайн. Какова цель знать индекс элемента, если сбор может быть изменен в любое время, и индекс будет признан недействительным, при таких обстоятельствах, когда есть несколько читателей - писателей, он довольно ясно говорит мне, что Queue или Stack будут наиболее подходящими коллекциями или Сумка может быть хорошей. Словарь можно использовать также потому, что его индексы не являются недействительными, добавляя элементы в коллекцию, и если вам нужен параллельный доступ к списку, вы получили свои методы Parralel.For
Что я нахожу действительно странным - http://msdn.microsoft.com/en-us/library/dd381935.aspx здесь мы можем прочитать о классе ConcurrentLinkedList, но я не могу найти его в System.dll, только Bag и BlockingCollection.
Я бы также сказал, что вероятность 95% по крайней мере такова, что любой из двух правдов о вашей проблеме
- Методы параллельного класса лучше
чем ConcurrentList
- Существующие Параллельные коллекции собираются быть лучше, чем ConcurrentList
Я бы также сказал, что, не предоставляя ConcurrentList, они сохранили разработчиков, которые ошибочно выбрали ConcurrentList, чтобы решить свои проблемы, сделав много ошибок, и сэкономили им много времени, заставляя разработчиков использовать существующие параллельные коллекции.
Ответ 3
Подумайте, как произвольный доступ (подразумеваемый IList<T>
) может работать в многопоточной среде. На самом деле вы действительно ничего не можете сделать без его неизменности, поскольку добавление и удаление, даже если они являются атомарными, не препятствуют тому, чтобы поток 1 удалял элемент в индексе, который только что должен был получить поток 2. Вот почему материал SyncRoot ушел в .NET 2.0 +