Очередная статья о 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 { // в течении заданного времени семафор остался на нуле }

На этом все, спасибо за внимание.

Все части:

  • Часть 1
  • Часть 2
  • Часть 3

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *