«Потокобезопасный» - это досадный термин, потому что у него нет четкого определения. По сути, это означает, что определенные операции над объектом гарантированно ведут себя разумно, когда объект работает через несколько потоков.
Рассмотрим простейший пример: счетчик. Предположим, у вас есть два потока, которые увеличивают счетчик. Если последовательность событий идет:
- Нить, которую читает со счетчика, получает
ноль.
- Тема два читает из счетчика, получает
ноль.
- Поток один увеличивает ноль, пишет
один, чтобы противостоять.
- Поток два шага ноль, пишет
один на счетчик.
Тогда обратите внимание, как счетчик «потерял» одно из приращений. Простые операции приращения на счетчиках не являются потокобезопасными; чтобы сделать их потокобезопасными, вы можете использовать блокировки или InterlockedIncrement.
Аналогично с очередями. Не-потокобезопасные очереди могут «потерять» очереди так же, как счетчики, не поддерживающие нить, могут потерять приращения. Хуже того, небезопасные очереди могут даже аварийно завершить работу или привести к сумасшедшим результатам, если вы неправильно используете их в многопоточном сценарии.
Сложность с «потокобезопасностью» заключается в том, что она не четко определена. Означает ли это просто "не потерпит крах"? Значит ли это, что будут получены разумные результаты? Например, предположим, что у вас есть «потокобезопасная» коллекция. Этот код правильный?
if (!collection.IsEmpty) Console.WriteLine(collection[0]);
Нет. Даже если коллекция является «потокобезопасной», это не означает, что этот код правильный; другой поток мог сделать коллекцию пустой после проверки, но до записи, и, следовательно, этот код мог аварийно завершиться, даже если объект якобы является «потокобезопасным». На самом деле определить, что каждая соответствующая комбинация операций является поточно-ориентированной, чрезвычайно сложно.
Теперь перейдем к вашей реальной ситуации: тот, кто говорит вам: «Вы должны использовать класс Queue, лучше, потому что он потокобезопасен», вероятно, не имеет четкого представления о том, о чем он говорит. Во-первых, очередь не является потокобезопасной. Во-вторых, не имеет значения, является ли очередь потокобезопасной или нет, если вы используете объект только в одном потоке! Если у вас есть коллекция, доступ к которой будет осуществляться в нескольких потоках, то, как я указал в моем примере выше, вам будет чрезвычайно трудно решить проблему, независимо от того, является ли сама коллекция «поточно-безопасной». Вы должны определить, что каждая комбинация операций , которую вы выполняете с коллекцией, также является потокобезопасной. Это очень сложная проблема, и если с ней вы столкнулись, вам следует воспользоваться услугами эксперта по этой сложной теме.