Могу ли я, без блокировки, безопасно вызвать List.AddRange (r) из нескольких потоков? Если нет, с какими неприятностями я столкнулся бы?Есть ли список <T> .AddRange() потокобезопасный?
ответ
No, its documentation не говорит, что это безопасный поток, поэтому его нет.
Публичный статический (общий в Visual Basic) Элементы этого типа являются потокобезопасными. Любые члены экземпляра не являются гарантированно надежными потоками.
Относительно того, что может пойти не так, подумайте о чем AddRange (newItems) делает:
- Проверьте, достаточно ли места в внутреннем массиве
- Если нет:
- Выделяют новый массив
- Скопируйте текущие элементы в новый массив
- Установите поле, чтобы указать на новый arr ау
- Скопировать в newItems на правильный локальный во внутреннем массиве
- Update «счетчик» поля (используется для управления, в который вставлен следующий пункт)
Теперь подумайте, что будет если вышеперечисленное смешивается с другим вызовом AddRange() или даже просто для вызова элемента.
Нет, он не является потокобезопасным.
Тема А может быть вызвана AddRange в вашем списке. Он может частично перебираться по потокам коллекции и переключения.
Резьба B может вызвать Add/Remove и т. Д., Прежде чем Thread A закончит.
Нет, это не так, но я бы хотел добавить, что более эффективно делать myList.AddRange(...);
в замке, чем делать несколько lock (syncLock) { myList.Add(...) };
.
С какой проблемой вы столкнулись бы? Когда один поток добавляет элемент, а другой перечисляет список, List<T>
выдает определенное исключение, потому что он выполняет некоторое внутреннее управление версиями, так как он хочет, чтобы наши бедные разработчики не сталкивались с неприятными побочными эффектами.
Также List<T>
содержит массив, в котором хранятся его элементы. Возможно, настройка элемента в массиве довольно атомарна, но всякий раз, когда достигается пропускная способность этого массива, будет создан новый, и элементы будут скопированы из старого. Поэтому, когда поток хочет что-то добавить, пока это копирование происходит, вы можете себе представить, что вещи перестанут синхронизироваться.
Отличный ответ, спасибо. =) –
До .NET Framework 4.0 коллекции .NET не являются потокобезопасными. Затем вам потребуется заблокировать его, прежде чем вы получите доступ к нему в своем коде
Collections and Synchronization (Thread Safety)
.
С другой стороны, .NET Framework 4.0 вводит новое пространство имен System.Collections.Concurrent
, которое включает мелкозернистые Thread-Safe Collections
.
И, наконец, если вы можете использовать .NET Framework 4.0, я настоятельно рекомендую вам сделать это за то, что вам нужно, в противном случае обязательно заблокируйте сборку каждый раз, когда вы хотите изменить или получить к ней доступ.
Кроме того, статическая коллекция должна быть потокобезопасной, но будьте осторожны, так как члены не гарантируются.
EDIT # 1
После дальнейшей проверки в связи с комментарием Стива Таунсенда, я признаю, что есть три поточно-коллекции в рамках .NET Framework, начиная с версии 3.0:
- SynchronizedCollection Generic Class;
- SynchronizedKeyedCollection Generic Class;
- SynchronizedReadOnlyCollection Generic Class.
Прошу прощения, я только что узнал их выход. =)
не верно, есть некоторые в 'System.Collections.Generic', которые работают здесь и предшествуют 4.0 –
@Steve Townsend: После проверки вы правы, я ошибаюсь. Кроме того, коллекция 'IList
Нет проблем. Я должен вам +1 за упоминание 4,0 коллекций. –
В зависимости от вашего использования, SynchronizedCollection может работать.
У вас не было бы ни одного выстрела AddRange
. Если вы используете это только для семени коллекции, вы можете сделать это, так как существует перегрузка конструктора IEnumerable
.
+1 Я только что узнал что-то новое сегодня! Благодаря! =) –
Спасибо за ваше возвышение. Я хотел бы сообщить вам, что я отредактировал свой ответ, чтобы отразить эту новую информацию, которую вы предоставили мне (всем нам). –
- 1. Должен ли AddRange() возвращает список
- 2. Список <T> (Список <T>) Конструктор потокобезопасный?
- 3. Список <T> .AddRange реализация suboptimal
- 4. Список <>. AddRange - where раздел
- 5. Список <Tuple<T>> | AddRange с массивами
- 6. Возвращает IEnumerable <> потокобезопасный?
- 7. Список многопотоков AddRange
- 8. Список <T> .AddRange/InsertRange создание временного массива
- 9. Список AddRange из определенного индекса?
- 10. Как отсортировать список после AddRange?
- 11. Оптимизированный потокобезопасный список в java
- 12. Есть ли способ преобразования Т к IEnumerable <T> без использования Добавить или AddRange
- 13. LIST <> AddRange бросали ArgumentException
- 14. Как добавить список в comboBox AddRange?
- 15. Есть ли AddRange эквивалент для HashSet в C#
- 16. Есть ли способ проверить нулевой объект в методе linq AddRange()?
- 17. Есть ли способ отметить код как не-потокобезопасный в C#?
- 18. Проверьте, есть ли список <Of List<T>> Список <T>
- 19. Самый эффективный, но потокобезопасный список/набор
- 20. EF Core: AddRange (список) работает неправильный OverLoad
- 21. Существует ли потокобезопасный клиент statsd?
- 22. Может ли CAS (Jasig) перезагрузить сервер TGT?
- 23. Force Renew TGT
- 24. Kerberos TGT Behavior
- 25. Как создать пользовательский потокобезопасный IList <T>?
- 26. C# List <object> AddRange of DBNull.Value
- 27. Могу ли я создать потокобезопасный std :: atomic <vector<int>>?
- 28. Есть ли список Java-классов с потоками?
- 29. Есть ли элегантный способ конвертировать список <Double> в список <Number>?
- 30. CAS: Расшифровка TGT
btw - re 'какая проблема?' - вы, скорее всего, получите исключение, в какое-то случайное время, когда конфликты нескольких потоков –