Это похоже на чрезмерно сложный способ думать об этом, и есть много мелких деталей этого описания, которые не совсем правы. В частности, «это происходит сразу по текущему потоку» неверно.
Прежде всего, давайте вернемся назад: различие между dispatch_async
и dispatch_sync
состоит только в том, ожидает ли его текущий поток или нет. Но когда вы отправляете что-то в последовательную очередь, вы всегда должны думать, что он работает на отдельном рабочем потоке по собственному выбору GCD. Да, в качестве оптимизации иногда dispatch_sync
будет использовать текущий поток, но вы никоим образом не гарантируете этот факт.
Во-вторых, когда вы обсуждаете dispatch_sync
, вы говорите что-то об этом «немедленно». Но это никоим образом не гарантировано, чтобы быть незамедлительным. Если нить выполняет dispatch_sync
в какой-то последовательной очереди, то этот поток будет блокироваться до тех пор, пока (а) не будет выполнен какой-либо текущий блок в завершении последовательной очереди; (b) любые другие блоки в очереди для выполнения этой очереди и завершения этой очереди; и (c), очевидно, блок, который сам поток отправил, запускается и завершается.
Теперь, когда вы используете последовательную очередь для синхронизации для некоторого потокобезопасного доступа к некоторому объекту в памяти, часто этот процесс синхронизации выполняется очень быстро, поэтому ожидающий поток обычно блокируется в течение незначительного промежутка времени, его отправленный блок (и любые предыдущие отправленные блоки), чтобы закончить. Но в целом, вводить в заблуждение сказать, что он будет работать немедленно. (Если это всегда можно запустить сразу, вам не нужна очередь для синхронизации доступа).
Теперь Ваш вопрос говорит о «критической области», к которой я предполагаю, что вы говорите о каком-то немного кода, для того, чтобы обеспечить безопасность потоков или по какой другой причине, как это, должно быть синхронизированы. Таким образом, при запуске этого кода, который будет синхронизироваться, единственный вопрос: re dispatch_sync
vs dispatch_async
- это то, должен ли текущий поток ждать.Например, общий шаблон состоит в том, что можно записать dispatch_async
в какую-либо модель (потому что нет необходимости ждать обновления модели перед продолжением), но dispatch_sync
читает с некоторой модели (потому что вы, очевидно, не хотите продолжать пока не будет получено значение read).
Дополнительная оптимизация этого шаблона синхронизации/асинхронизации является шаблоном считывающего устройства, где допускаются одновременные чтения, но одновременная запись не является. Таким образом, вы будете использовать параллельную очередь, dispatch_barrier_async
записи (достижение последовательного поведения для записей), но dispatch_sync
чтение (получение одновременной производительности по отношению к другим операциям чтения).
Критическая область - другое имя для критического раздела: https://en.wikipedia.org/wiki/Critical_section –
Да, это то, что, как я думал, вы имели в виду. В iOS мы говорим о том, что нужно «синхронизировать». См. [Руководство по программированию потоков: синхронизация] (https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/Multithreading/ThreadSafety/ThreadSafety.html#//apple_ref/doc/uid/10000057i-CH8-SW1). Но это предшествует GCD, о котором говорится в [Руководстве по программированию параллелизма: устранение кода на основе блокировки] (https://developer.apple.com/library/content/documentation/General/Conceptual/ConcurrencyProgrammingGuide/ThreadMigration/ThreadMigration.html#//apple_ref/DOC/UID/TP40008091-CH105-SW3). – Rob
Да. Таким образом, я был немного неряшлив, говоря о вещах немедленно, но у меня было то, что он делал правильно. К счастью, я могу упростить до 1 очереди сообщений для реализации Android, не имея архитектуры, построенной вокруг основных уведомлений о данных, что упрощает работу. –