Разница между dispatch_async и dispatch_sync в последовательной очереди?

Я создал серийную очередь следующим образом:

    dispatch_queue_t _serialQueue = dispatch_queue_create("com.example.name", DISPATCH_QUEUE_SERIAL);

Какая разница между dispatch_async, называемым так

 dispatch_async(_serialQueue, ^{ /* TASK 1 */ });
 dispatch_async(_serialQueue, ^{ /* TASK 2 */ });

И dispatch_sync вызывается так в этой последовательной очереди?

 dispatch_sync(_serialQueue, ^{ /* TASK 1 */ });
 dispatch_sync(_serialQueue, ^{ /* TASK 2 */ });

Я понимаю, что независимо от того, какой метод отправки используется, TASK 1 будет выполняться и завершаться до TASK 2, исправить?

Ответ 1

Да. Использование последовательной очереди обеспечивает последовательное выполнение задач. Единственное отличие состоит в том, что dispatch_sync возвращается только после завершения блока, тогда как dispatch_async возвращает после того, как он добавлен в очередь и может не закончиться.

для этого кода

dispatch_async(_serialQueue, ^{ printf("1"); });
printf("2");
dispatch_async(_serialQueue, ^{ printf("3"); });
printf("4");

Он может печатать 2413 или 2143 или 1234, но 1 всегда до 3

для этого кода

dispatch_sync(_serialQueue, ^{ printf("1"); });
printf("2");
dispatch_sync(_serialQueue, ^{ printf("3"); });
printf("4");

он всегда печатает 1234


Примечание. Для первого кода он не будет печатать 1324. Поскольку printf("3") отправляется после выполнения printf("2"). И задача может быть выполнена только после отправки.


Время выполнения задач ничего не меняет. Этот код всегда печатает 12

dispatch_async(_serialQueue, ^{ sleep(1000);printf("1"); });
dispatch_async(_serialQueue, ^{ printf("2"); });

Что может случиться, это

  • Тема 1: dispatch_async трудоемкая задача (задача 1) в последовательную очередь
  • Тема 2: запуск выполнения задачи 1
  • Тема 1: dispatch_async еще одна задача (задача 2) в последовательную очередь
  • Тема 2: задача 1 завершена. запустить выполнение задачи 2
  • Тема 2: задача 2 завершена.

и вы всегда видите 12

Ответ 2

Разница между dispatch_sync и dispatch_async проста.

В обоих примерах TASK 1 всегда будет выполняться до TASK 2, потому что он был отправлен до него.

Однако в примере dispatch_sync вы не отправляете TASK 2 до тех пор, пока TASK 1 не будет отправлен и не будет выполнен. Это называется "blocking" . Ваш код ждет (или "блокирует" ) до выполнения задачи.

В примере dispatch_async ваш код не будет ждать завершения выполнения. Оба блока отправят (и будут выставлены в очередь) в очередь, а остальная часть вашего кода продолжит выполнение этого потока. Затем в какой-то момент в будущем (в зависимости от того, что еще было отправлено в вашу очередь), TASK 1 выполнит, а затем выполнит TASK 2.