Я пытаюсь выяснить параллельные коллекции в С#.
ConcurrentBag, ConcurrentDictionary и ConcurrentQueue.
Возможно ли, чтобы несколько потоков одновременно добавляли к ним элементы ТОЧНО? Или они ждут друг друга?
Я пытался изучить их исходный код, но не мог сказать наверняка.
Я вижу здесь, что есть ответ для С++, но я хотел бы знать, так ли это и для С#?
Дайте определение «одновременно»? Для добавления элемента потребуется несколько инструкций ЦП, которые затем преобразуются в микрооперации внутри процессора и отправляются в эту большую суперскалярную систему, которая планирует и переупорядочивает микрооперации по желанию. Могут ли два потока одновременно выполнять одни и те же инструкции для добавления двух элементов? Возможно, но это маловероятно: современные процессоры так не работают. Это также зависит от коллекции: у них часто есть пути без блокировки и пути, которые требуют блокировки, в зависимости от различных условий.
В самом общем смысле ответ состоит в том, что дополнения сериализованы, т. е. они ждут друг друга.
Точный механизм зависит от множества условий, и, насколько это возможно, они пытаются сделать это без блокировок (связанные обмены вместо блокировок или мьютексов), но есть некоторые пути, которые требуют блокировок (с первого взгляда, если внутренний массив нуждается для изменения размера или если кто-то другой запрашивает, например, синхронизированное перечисление).
Это не доказуемо на программном уровне. Это означает, что вы не можете написать программу, которая может доказать или опровергнуть теорию о том, что два элемента могут быть вставлены двумя потоками в одну и ту же коллекцию в одно и то же время.
Одна из попыток доказать это состоит в том, чтобы третий поток действовал как наблюдатель, который многократно перечислял бы коллекцию в тесном цикле, в то время как два других потока выполняли бы две одновременные вставки. Предположим, что поток-наблюдатель обнаружил ноль элементов в одном перечислении и два элемента в следующем перечислении, что это доказывает? Поток может быть приостановлен операционной системой в любой момент на время, измеряемое миллисекундами, так что вы не узнали ничего окончательного о рассматриваемой проблеме. Две вставки могли произойти в одно и то же время или с разницей в несколько миллисекунд, кто знает?
Если вы хотите ответить на этот вопрос на аппаратном уровне, то на этом уровне понятия "коллекция" не существует. У вас есть регистры, инструкции ЦП, микросхемы памяти и т. д. На этом уровне нет программных объектов, о которых можно было бы говорить.
@MiBuena Solomon Slow отвечать может быть более полезным и информативным, чем мой. ?
да, там немного подробнее. Тем не менее оба ответа очень полезны. :) Большое спасибо. :)
Добавление объекта в коллекцию — непростая операция. Это последовательность из События.
События могут быть одновременными, но когда мы говорим о последовательности событий, это либо последовательности перекрывать,, либо последовательности непересекающийся..
Аппаратное обеспечение компьютера спроектировано таким образом, что если два события происходят одновременно, результатом всегда будет будто, одно из которых произошло раньше другого. Причина проста. Предположим, что поток A присваивает v=3
, а поток B присваивает v=5
. Если нить A идет первой, окончательный результат будет v==5
. Если нить B пойдет первой, окончательный результат будет v==3
. Ни один программист никогда не захочет иметь дело с третьим возможным исходом. Что бы это было?
Независимо от того, что происходит на оборудовании, когда мы говорим о События в программах, мы никогда не говорим «одновременно». Мы верим, что аппаратное обеспечение будет вести себя как будто, такой возможности не существует.
Когда мы говорим о перекрывающихся последовательностях операций (например, о добавлении объектов в некоторую коллекцию), это вызывает серьезную озабоченность. Вот что такое управление параллелизмом.
Если управление параллелизмом выполнено правильно, то после того, как каждый из двух потоков вставит объект в коллекцию, коллекция будет гарантированно содержать оба объекта. Если это сделано неправильно, возможно почти все (включая возможность того, что любая дальнейшая попытка использовать коллекцию приведет к сбою программы).
Вы можете буквально потратить годы на изучение всех различных методов управления параллелизмом.
Это плохой пост, но вы можете найти ответ здесь: stackoverflow.com/questions/28781817/…