Пытаюсь понять разницу между коллекциями ConcurrentBag<T>
и List<T>
по этой статье.
Мне почему-то казалось, что если я буду использовать List<T>
и в тот момент, когда один поток будет туда что-то записывает и попытается тоже самое сделать другой поток, то выскочит exception, но нет, все работает.
Есть сценарий мультипоточной обработки, где в конце своей работы все потоки должны записывать свой результат в одну коллекцию:
class Program
{
static void Main(string[] args)
{
var results = new List<string>();
//var results = new ConcurrentBag<string>();
// STEP 1: Get results.
Parallel.For(1, 50000, idx =>
{
// Some process.
//...
results.Add("something");
});
// STEP 2: Process results.
foreach (var result in results)
{
//...
}
}
}
Какое преимущество я получаю в случаи использования ConcurrentBag<T>
вместо List<T>
в моем случаи?
И еще такой маленький подвопрос: results
, его правильно называть разделяемым ресурсом?
Мне почему-то казалось, что если я буду использовать List и в тот момент, когда один поток будет туда что-то записывает и попытается тоже самое сделать другой поток, то выскочит exception
Проблема может возникнуть, а может и не возникнуть. Это и называется потоконебезопасная коллекция - когда проблема потенциально может быть. Сегодня работает, завтра упадет - так как нет гарантии, что при параллельной работе 2 потока не попытаются писать одновременно в список.
То, что список у вас внутри Parallel.For
ещё не гарантирует параллельного доступа. Параллельный доступ - это когда в одну и ту же единицу времени 2 или более потока пытаются работать со списком. В вашем случае при первом, втором, третем запусках такого может и не случиться, но на 99 запуске код упадет.
мультипоточной обработки
Многопоточной
Какое преимущество я получаю в случаи использования ConcurrentBag вместо List
В случае выбора ConcurrentBag<T>
вы получаете гарантию, что ваш код не упадет в многопоточной работе. При работе с List<T>
никаких гарантий нет, нет даже гарантий от потери данных, не то, чтобы от исключений. Повторю - даже один и тот же многопоточный код может в 99 случаях сработать и в 1 случае упасть при работе с потоконебезопасными коллекциями.
results, его правильно называть разделяемым ресурсом?
Поскольку потоки его разделяют, то да
В конкретно вашем коде лично я не вижу смысла в разделении ресурса, гораздо проще написать так:
var results = Enumerable
.Range(1, 50000)
.AsParallel()
.Select(x=> /*....*/)
.ToList();
foreach (var result in results)
{
//...
}
Мне почему-то казалось, что если я буду использовать List и в тот момент, когда один поток будет туда что-то записывает и попытается тоже самое сделать другой поток, то выскочит exception, но нет, все работает.
List<T>
не является потокобезопасным. Это означает, что он вообще не предпринимает никаких действий для защиты данных при доступе из разных потоков. Ни блокировок, ни даже проверок на одновременный доступ.
Исключения вы не получите, но и гарантии целостности данных - тоже. Используйте ConcurrentBag<T>
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Есть ListView в который записывается данные, дело в том что нету возможности записать все сразу, по этому необходимо изменять/обновлять данные...
Будет кнопка, и если удержать на этой кнопке мышку секунду где-то 05 будет появляться окно с текстом
На GitHub есть репозиторий с реализацией декодирования фреймов протокола WebSocketПроблема в том, что если в один момент времени отправляется много...
я составляю cms на laravel c возможность расширяться через плагиныВозник вопрос, у меня есть пользователи и каждому можно задавать роли админ...