Стек у каждого потока свой, а куча?
Ответ
Стек — свой у каждого потока: он создаётся вместе с потоком (главный — 1 МБ на iOS, фоновые Thread и GCD-потоки — 512 КБ по умолчанию, размер можно задать через Thread.stackSize) и уничтожается вместе с ним. Фрейм функции виден только тому потоку, который её вызвал, поэтому локальные переменные потокобезопасны «по построению».
Куча — одна на процесс, общая для всех потоков. Любой объект, до которого два потока могут дотянуться по ссылке, — это разделяемое состояние: чтение и запись нужно синхронизировать (actor, Mutex/OSAllocatedUnfairLock, serial queue), иначе data race.
Продолжение ответа с кодом и уточняющими вопросами интервьюера — в приложении DevPrep.
Полный ответ — в DevPrep