Предположим, у меня имеется List<T>
, который одновременно читает один поток, а другой в него пишет. В данному случае что было бы правильнее и быстрее использовать: volatile или ConcurrentBag?
О скорости можно говорить лишь тогда, когда у вас имплементирована функциональность, и профилирование показывает, что доступ к данным является bottleneck'ом. Поэтому давайте разберёмся с корректностью.
Начнём с того, что volatile
мы не можем применить к списку — volatile
-поля могут быть только элементарных типов. Даже если бы его можно было применить, что толку в синхронизации доступа к ссылке на контейнер? Гонки-то у нас по данным внутри контейнера.
ConcurrentBag
— это более разумный выбор. Но это только если реально данные лишь добавляются в одном из потоков, а не модифицируются им. В зависимости от вашей точной задачи, может понадобиться ConcurrentBag
(если не важен порядок) или ConcurrentQueue
(если важен).
Если нужен доступ по индексу, или модификация данных в пишущем потоке (например: collection[i]++
), не стоит искать выгоду в несколько микросекунд, проще и безопаснее использовать нормальный lock
.
В данном случае правильнее volatile
, т.к. пишет в лист только 1 поток.
ConcurrentBag
использовать можно и работать будет тоже правильно, другое дело, что потокобезопасные коллекции в принципе всегда работают медленнее обычных, а так как в данном случае никаких ошибок при записи не предвидится, то использование ConcurrentBag
выглядит излишним.
В случае если планируется писать с 2х и более потоков, то, конечно без использования ConcurrentBag
или lock
не обойтись.
Есть xml файл, у каждой ноды есть 2 атрибута, допустим name и number, хочу сделать ListBox с сортировкой по одному из атрибутов, для наглядности xml:
Останавливаю службы из списка List<string> таким способом: