Ответ зависит в некоторой степени от того, что вы делаете с содержимым массива.
В некоторой степени вопрос не имеет большого смысла - если поток a должен ждать, пока весь массив не будет заполнен в потоке b, то почему бы просто не выполнить заполнение в потоке a? Что еще он делает во время ожидания массива?
В качестве альтернативы, если поток a может продвигаться вперед по мере получения каждого элемента массива, тогда может иметь больше смысла передавать каждую полученную запись массива из потока b в поток a по мере их создания. В этом случае у вас фактически есть очередь, которая является общим шаблоном производителя / потребителя для многопоточной работы - поток b заполняет очередь, из которой поток читает данные.
См. Раздел «Использование объекта NSConditionLock» ссылки, которую Кай опубликовал для примера блокировки производителя / потребителя.