Найти в Дзене
Даниил Зазулин

Swift. Немного о понимании многопоточности при работе с GCD.

Одним из основных инструментов для работы с многопоточностью является GCD. Вроде всё понятно: при работе с GCD мы работаем с потоками не напрямую, а через очереди (queue), добавляя в них задачи (замыкания), которые выдергивается системой по принципу FIFO. Очередь может последовательная (.serial) или параллельная (.concurrent). И напоследок, задачи можно добавлять в очередь синхронно (.sync) или (.async), тут, как мне кажется, и возникают проблемы и вопросы. Блокирует ли параллельную очередь синхронное добавление задачи? Для того, чтобы получить ответ рассмотрим два примера.

Пример №1
Пример №1

Для первого примера создадим свою очередь с атрибутом .concurrent и попробуем добавить последовательно две задачи синхронно. Запустим, посмотрим что выведется на экран.

Выполнения кода из примера №1
Выполнения кода из примера №1

По тому что-то вывел нам компилятор видно, что когда мы создаем очередь, это не значит, что задачи будут выполняться на другом потоке. Мы так же остаемся на главном, только система будет брать сначала задачи с очереди с более высоким приоритетом. Так же видно, что все задачи выполнились последовательно, но появляется вопрос синхронное добавление задачи блокирует всю очередь или только текущий поток? Для ответа рассмотрим другой кейс.

Пример №2
Пример №2

Во втором примере синхронные добавления в нашу очередь будет выполняться внутри асинхронных вызовов внутри глобальной очереди. Запустим, посмотрим что выведется на экран.

Выполнения кода из примера №2
Выполнения кода из примера №2

То что выведет нам компилятор для второго случая многих удивит. Разберем почему так произошло. Но первое, что можно заметить, что задачи выполняются с разных потоков, это произошло из-за того что мы добавили задачу асинхронно, поэтому выполнение началось на другом потоке. Второе, что мы видим, что задачи выполняются непоследовательно. То есть, синхронно добавленные задачи с разных потоков в concurrent queue будут выполняться параллельно.

Можно подытожить. Когда мы говорим о concurrent queue, мы подразумеваем, что не очередь будет одновременно работать с разными потоками, а с очередью можно работать одновременно с разных потоков и когда мы добавляем задачу синхронно в очередь, мы блокируем не очередь, а текущий поток.