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