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