Перед ожиданием вы должны удерживать блокировку переменной состояния. Ожидание отпускает блокировку, затем гарантируется блокировка до тех пор, пока она не будет сигнализирована, и блокировка была повторно принята. Обратите внимание, что если несколько потоков ждут, только один будет уведомлен о сигнале, остальные будут продолжать ждать дальнейших сигналов. В качестве альтернативы, если предикат останется истинным после выполнения, тогда сигнал может быть передан всем потокам.
Блокировка - это блокировка взаимного исключения (mutex), что означает, что только один поток может удерживать блокировку в любой момент времени. Помимо использования этого для защиты того, что вы используете для переменной условия, оно также защищает внутренние действия переменной условия. Если вы попытаетесь использовать его без блокировки, тогда будут условия гонки при проверке/установке условия для нескольких потоков.
Для правильного использования переменной условия, ни один из ваших примеров верен. Все дело в том, чтобы защитить состояние предиката. Вот пример, основанный на псевдокоде от the documentation.
NSCondition condvar = [NSCondition new];
__block BOOL workRequired = NO;
// something somewhere else does this at some point ^{
[condvar lock];
workRequired = YES;
[condvar signal];
[condvar unlock];
};
[condvar lock];
while (!workRequired) {
[condvar wait];
}
// Do the work
workRequired = NO;
[condvar unlock];
В вашем примере у вас нет никаких условий, кроме «законченного блока». В этом случае вам следует просто использовать dispatch_sync.
dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// Do stuff
};
// Do rest
Если по каким-то причинам вы не знаете, если вы уже работаете в этой очереди, то semaphore будет достаточно.
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0L);
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// Do stuff
dispatch_semaphore_signal(semaphore);
};
dispatch_semaphore_wait(semaphore);
// Do rest
В дополнение к проблемам, которые вы отметили, OP блокируется на одном потоке и разблокируется на другом, что не является законным. –