Dispatch_async vs. dispatch_sync, используя последовательные очереди в Grand Central Dispatch
Хорошо, мне нравится Grand Central Dispatch и после его использования с относительным успехом, но это то, что я не совсем понимаю.
Предположим, что я создал свою собственную последовательную очередь, используя
dispatch_queue_t myQueue;
myQueue = dispatch_queue_create("myQueue", NULL);
После этого я делаю это:
dispatch_async(myQueue, ^{
[self doStuff1];
});
// and a few lines later...
dispatch_sync(myQueue, ^{
[self doStuff2];
});
Первая отправка - асинхронная. Итак, это будет сделано одновременно, не так ли? Как это может случиться, если myQueue является серийным? Как последовательная очередь может делать что-то параллельно или, если хотите, вышла из строя?
спасибо
Ответы
Ответ 1
dispatch_async()
означает, что блок выставлен в очередь, а dispatch_async()
возвращается в очередь на очередность другой задачи/блока (возможно) до выполнения блока.
С dispatch_sync()
, блок находится в очереди, и функция не будет продолжать задавать другую задачу/блок до тех пор, пока блок не будет выполнен.
Блоки все еще выполняются серийно. Вы могли бы выполнить 100 dispatch_async()
вызовов, каждый из которых имеет блок, который будет спать в течение 100 секунд, и это будет очень быстро. Следуйте за этим вызовом dispatch_sync()
в той же последовательной очереди, а dispatch_sync()
вернется через ~ 10000 секунд.
Проще говоря:
dispatch_async(serialQ, block1);
dispatch_async(serialQ, block2);
dispatch_sync(serialQ, block3);
block1
будет выполнен до block2
, который будет выполнен до block3
. Это порядок, гарантированный последовательной очередью.
Однако вызовы dispatch_async()
могут возвращаться до того, как какой-либо из блоков начнет выполнение. dispatch_sync()
не будет возвращаться до того, как будут выполнены все три блока!
Ответ 2
Ни один из dispatch_async
или dispatch_sync
не меняет способ блокирования блока. Если очередь является последовательной, блоки будут выполняться последовательным образом, если очередь является параллельной, одновременно.
Важное различие между ними состоит в том, что dispatch_sync
ставит в очередь блок и ожидает текущий поток выполнения до тех пор, пока этот блок не будет выполнен, а dispatch_async
просто остановит блок и продолжит выполнение последующих инструкций.
Ответ 3
Последовательная очередь может запускать только одну задачу за раз, независимо от синхронизации или асинхронности. Последовательные очереди выделяются только одному потоку. Это будет легче понять, используя приведенный ниже пример -
Предположим, что есть 2 очереди A и B, выполняющие задачи T1 и T2 соответственно, и T1 выполняется асинхронно. Если управление переходит от A к B и B выполняет синхронно T2, то до тех пор, пока T2 (блок кода в блоке dispatch_sync) не завершит выполнение, T1 будет заблокирован. Когда T2 завершится, T1 возобновит его выполнение.