Ответ
Нет, стандартный System.Collections.Generic.Stack<T> не является потокобезопасным. Его методы не защищены от состояния гонки при одновременном вызове из нескольких потоков, что может привести к повреждению внутренней структуры данных, потере элементов или исключениям.
Способы обеспечения потокобезопасности:
-
Явная синхронизация с помощью
lock: Самый простой способ для контролируемого доступа.private Stack<int> _stack = new Stack<int>(); private readonly object _syncLock = new object(); public void PushSafely(int item) { lock (_syncLock) { _stack.Push(item); } } public bool TryPopSafely(out int result) { lock (_syncLock) { if (_stack.Count > 0) { result = _stack.Pop(); return true; } result = default; return false; } } -
Использование
ConcurrentStack<T>: Специализированная потокобезопасная коллекция из пространства имёнSystem.Collections.Concurrent. Она использует эффективные lock-free алгоритмы для отдельных операцийPushиTryPop.using System.Collections.Concurrent; ConcurrentStack<int> concurrentStack = new ConcurrentStack<int>(); // Потокобезопасные операции concurrentStack.Push(10); concurrentStack.Push(20); if (concurrentStack.TryPop(out int poppedItem)) { Console.WriteLine("Popped: " + poppedItem); // Может быть 20 или 10 }Важно: Хотя
ConcurrentStackгарантирует атомарность отдельных операций, последовательность вызовов (например,if(stack.Count>0) stack.Pop()) по-прежнему требует внешней синхронизации, так как между проверкой и действием состояние может измениться другим потоком. Для таких сценариев используйтеTryPop.