dispatch async vs dispatch порядок выполнения синхронизации
у меня есть очередь последовательной отправки, созданная с помощью:
dispatch_queue_t serialQueue = dispatch_queue_create("com.unique.name.queue", DISPATCH_QUEUE_SERIAL);
Я хочу использовать эту последовательную очередь для обеспечения безопасности потока для доступа к классу, автоматически выполняя асинхронную работу, которая не должна возвращаться в вызывающий поток.
- (void)addObjectToQueue:(id)object
{
dispatch_async(serialQueue, ^{
// process object and add to queue
});
}
- (BOOL)isObjectInQueue:(id)object
{
__block BOOL returnValue = NO;
dispatch_sync(serialQueue, ^{
// work out return value
});
return returnValue;
}
Если я вызову метод addObjectToQueue:, то немедленно вызовите метод isObjectInQueue:, они гарантированно будут выполняться в том же порядке, или будет/может isObjectInQueue выполнить первым?
In другими словами, dispatch_async выполняет точно то же самое, что и dispatch_sync (планирование блока немедленно), за исключением того, что он не блокирует вызывающий поток?
Я видел подобные вопросы с ответами в обоих направлениях, поэтому я ищу окончательный ответ, желательно подкрепленный документацией Apple.
2 ответов
гарантируется ли их выполнение в том же порядке?
да.
будет / может
isObjectInQueue
выполнить первым?
да.
причина " да " для обоих ответов - вы должны рассмотреть возможность потоковой передачи. Предположительно, именно поэтому вы используете последовательную очередь в первую очередь. Вы делаете доступ к этой очереди потокобезопасным.
в основном, блоки будут выполняться в том порядке, в котором они ставятся в последовательную очередь. Это 100% гарантировано. Однако, если несколько потоков забивают на это, то один поток может войти первым, чтобы прочитать что-то из очереди, прежде чем другой успеет добавить его.
другими словами, dispatch_async выполняет точно то же самое, что и
dispatch_sync
(планирование блока немедленно), за исключением того, что он не блокирует вызывающий поток?
Это верно. В обоих случаях блок добавляется в очередь. Это тут же добавил. dispatch_sync
просто ждет завершения блока перед возвращением, тогда как dispatch_async
сразу возвращается.
Я думаю, ваш вопрос в том, будет ли основной поток продолжать работать, пока dispatch_async
все еще выполняется операция очереди? Я предполагаю, что это не будет, потому что это заслуживает прямого упоминания. Во всяком случае, я нашел это в dispatch_async.3 что предполагает, что это так:
концептуально, dispatch_sync() является удобной оболочкой вокруг dispatch_async() с добавлением семафора для ожидания завершение блока, и обертка вокруг блока сигнал о его завершение.
и действительно, если вы следуете исходный код dispatch_async в очереди.c вы увидите, что блок находится в очереди на переднем плане, и только после этого выполнение возвращается к коду, который вызвал dispatch_async
. Поэтому, если очередь является последовательной,dispatch_async
затем dispatch_sync
из того же потока будет очередь блоков в порядке.
, потому что dispatch_sync
будет блокировать до блока (и все блоки до в последовательная очередь) выполняются, тогда ваш код будет правильным. isObjectInQueue:
правильно сообщит, если объект, добавленный ранее, находится в очереди.
редактировать: в многопоточной среде я бы написал код выше как:
- (void)addObjectToQueue:(id)object
{
dispatch_barrier_async(_queue, ^{
// process object and add to queue
});
}
- (BOOL)isObjectInQueue:(id)object
{
__block BOOL returnValue = NO;
dispatch_sync(_queue, ^{
// work out return value
});
return returnValue;
}
потому что выполнение каждого метода может быть отложено в любой момент в пользу другого потока.