Многопоточность в iOS. Введение в GCD, часть 4, семафоры

Очередная статья о GCD. На этот раз познакомимся с семафорами, механизм которых предлагает нам GCD. Семафор позволяет выполнять какой-либо участок кода одновременно только конкретному количеству потоков. В основе семафора лежит счетчик, который и определяет, можно ли выполнять участок кода текущему потоку или нет. Если счетчик больше нуля — поток выполняет код, в противном случае — нет.
На семафоре определены три операции:
  • Создание семафора
  • Подождать, пока счетчик семафора станет больше нуля, уменьшить его на единицу и пройти далее
  • Увеличить счетчик на единицу

Что нам предлагает GCD?

Семафор в GCD представлен типом dispatch_semaphore_t. Для создания семафора существует функция dispatch_semaphore_create, которая принимает один аргумент — число потоков, которые могут одновременно выполнять участок кода. Выглядит это так:
dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
В данном случае, семафор позволит только одному потоку выполнять код. Если мы больше не нуждаемся в созданном семафоре, нужно его уничтожить:
dispatch_release(semaphore);
Вторая операция — операция ожидания семафора, осуществляется с помощью функции dispatch_semaphore_wait. У функции два аргумента: первый — семафор, второй — сколько времени ждать. Мы можем указать максимальное время ожидания, это точно так же, как мы и делали в dispatch_after. После того, как семафор станет больше нуля, функция dispatch_semaphore_wait «отпустит» поток и будет выполнен нужный участок кода. После этого обязательно нужно вызвать функцию dispatch_semaphore_signal (третья операция) и передать ей семафор. Эта функция увеличит значение семафора на единицу. Пример:
 // ожидаем бесконечно
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
/* код */
// увеличиваем значение семафора dispatch_semaphore_signal(semaphore);
Либо так:
// будем ждать одну секунду
dispatch_time_t waitTime = dispatch_time(DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC);
long result = dispatch_semaphore_wait(semaphore, waitTime);
if ( result == 0 ) { // семафор стал больше нуля
dispatch_semaphore_signal(semaphore); } else { // в течении заданного времени семафор остался на нуле }
На этом все, спасибо за внимание.