Синхронная отправка приостанавливает выполнение вашего кода до тех пор, пока отправленный блок не завершится. Асинхронная диспетчеризация возвращается немедленно, блок выполняется асинхронно с учетом вызывающего кода:
dispatch_sync(somewhere, ^{ something });
// Reached later, when the block is finished.
dispatch_async(somewhere, ^{ something });
// Reached immediately. The block might be waiting
// to be executed, executing or already finished.
И есть два вида очередей отправки: последовательная и параллельная. Последовательные отправляют блоки строго один за другим в порядке их добавления. Когда один заканчивается, другой начинается. Для такого выполнения необходим только один поток. Параллельные очереди отправляют блоки одновременно, параллельно. Там используются другие темы.
Вы можете смешивать и сопоставлять синхронизацию / асинхронную диспетчеризацию и последовательные / параллельные очереди по своему усмотрению. Если вы хотите использовать GCD для защиты доступа к критическому разделу, используйте одну последовательную очередь и отправьте все операции с общими данными в этой очереди (синхронно или асинхронно, не имеет значения). Таким образом, всегда будет только один блок, работающий с общими данными:
- (void) addFoo: (id) foo {
dispatch_sync(guardingQueue, ^{ [sharedFooArray addObject:foo]; });
}
- (void) removeFoo: (id) foo {
dispatch_sync(guardingQueue, ^{ [sharedFooArray removeObject:foo]; });
}
Теперь, если guardingQueue
- последовательная очередь, операции добавления / удаления никогда не могут конфликтовать, даже если методы addFoo:
и removeFoo:
вызываются одновременно из разных потоков.