На поточно-ориентированную коллекцию и не-поточно-безопасную коллекцию можно взглянуть по-другому.
Рассмотрим магазин без клерка, кроме как на кассе. Если люди не будут действовать ответственно, у вас будет масса проблем. Например, предположим, что покупатель достает банку из банки-пирамиды, в то время как клерк строит пирамиду, и весь ад вырвется наружу. Или, что, если два покупателя потянутся за одним и тем же товаром одновременно, кто выиграет? Будет ли драка? Это небезопасная коллекция. Существует множество способов избежать проблем, но все они требуют какой-то блокировки или, скорее, явного доступа в той или иной форме.
С другой стороны, представьте себе магазин с клерком за столом, и вы можете делать покупки только через него. Вы встаете в очередь и просите у него предмет, он возвращает его вам, и вы выходите из очереди. Если вам нужно несколько предметов, вы можете забрать столько предметов на каждом пути туда и обратно, сколько вы можете вспомнить, но вы должны быть осторожны, чтобы не задевать продавца, это разозлит других клиентов в очереди за вами.
Теперь рассмотрим это. Что, если в магазине с одним продавцом вы дойдете до конца очереди и спросите продавца: «У вас есть туалетная бумага?», И он скажет «Да», а затем вы скажете: «Хорошо, я» Я свяжусь с вами, когда узнаю, сколько мне нужно », тогда, когда вы снова окажетесь в очереди, магазин, конечно, можно будет распродать. Этот сценарий не предотвращается потокобезопасной коллекцией.
Потокобезопасная коллекция гарантирует, что ее внутренние структуры данных действительны в любое время, даже если к ней обращаются из нескольких потоков.
Коллекция, не обеспечивающая потокобезопасность, не дает таких гарантий. Например, если вы добавляете что-то в двоичное дерево в одном потоке, в то время как другой поток занят перебалансировкой дерева, нет никакой гарантии, что элемент будет добавлен, или даже если дерево все еще будет действительным после этого, оно может быть повреждено безнадежно.
Однако потокобезопасная коллекция не гарантирует, что все последовательные операции в потоке работают с одним и тем же «снимком» его внутренней структуры данных, что означает, что если у вас есть такой код:
if (tree.Count > 0)
Debug.WriteLine(tree.First().ToString());
вы можете получить исключение NullReferenceException, потому что между tree.Count
и tree.First()
другой поток очистил оставшиеся узлы в дереве, что означает First()
возврат null
.
Для этого сценария вам нужно либо проверить, есть ли у рассматриваемой коллекции безопасный способ получить то, что вы хотите, возможно, вам нужно переписать приведенный выше код или вам может потребоваться заблокировать.