Выделяется ли куча на каждый поток?

«Выделяется ли куча на каждый поток?» — вопрос из категории Управление памятью, который задают на 25% собеседований C# Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Нет. В .NET управляемая куча (Managed Heap) является общим ресурсом для всех потоков в рамках одного домена приложения (AppDomain).

  • Единая куча: Все потоки выделяют память для объектов (через new) в одной и той же куче.
  • Потокобезопасность выделения: Для предотвращения коллизий CLR использует внутренние механизмы синхронизации. Например, для быстрого выделения памяти в куче для малых объектов используется потоковый локальный кэш (Thread Local Allocation Buffer, TLAB), что минимизирует блокировки.
  • Индивидуальный стек: Каждый поток имеет свой собственный стек (stack) для хранения локальных переменных и контекста вызовов методов.

Пример и последствия:

// Этот список создается в общей куче
List<int> sharedList = new List<int>();

Task.Run(() => sharedList.Add(1)); // Поток 1
Task.Run(() => sharedList.Add(2)); // Поток 2
// Оба потока работают с одним объектом в куче -> требуется синхронизация!

Ключевое следствие: Поскольку куча общая, доступ к одним и тем же объектам из разных потоков требует применения примитивов синхронизации (lock, Mutex, SemaphoreSlim и т.д.) для обеспечения потокобезопасности.