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 возобновит его выполнение.