Какая разница между синхронными и асинхронными вызовами в Objective-C, а также многопоточными?

В течение самого долгого времени я думал, что асинхронный синоним запускает что-то в фоновом потоке, а синхронно - в основном потоке (блокируя обновления и взаимодействия UI). Я понимаю, что не работает на основном потоке для дорогостоящих действий, потому что он не позволяет выполнять действия пользовательского интерфейса, поскольку основной поток занят, но почему синхронно хлопотно?

Однако с тех пор мне стало известно, что вы можете совершать асинхронные вызовы в основном потоке и синхронные вызовы фоновых потоков.

Я всегда слышу, как люди говорят, что не используют дорогостоящие вызовы синхронно или в основном потоке, так как это блокирует пользовательский интерфейс для пользователя. Являются ли этими двумя отдельными вопросами, чтобы я не делал этого? Каковы различия?

Ответ 1

Когда вы вызываете что-то синхронно, это означает, что поток, инициировавший эту операцию, будет ждать завершения задачи перед продолжением. Асинхронный означает, что он не будет ждать.

Сказав это, когда люди предполагают, что вы выполняете медленный или дорогой процесс асинхронно, они неявно предполагают, что вы должны запускать его асинхронно, но вы должны делать это в фоновом потоке. Цель состоит в том, чтобы освободить основной поток, чтобы он мог продолжать реагировать на пользовательский интерфейс (а не на замораживание), поэтому вы отправляете задачи в фоновый поток асинхронно.

Итак, есть две части. Во-первых, используя GCD в качестве примера, вы получаете фоновую очередь (либо захватите одну из глобальных фоновых очередей, либо создайте свой собственный):

// one of the global concurrent background queues

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

// or you could create your own serial background queue:
//
// dispatch_queue_t queue = dispatch_queue_create("com.domain.app.queuename", 0);

Во-вторых, вы отправляете свои задачи в эту очередь асинхронно:

dispatch_async(queue, ^{
    // the slow stuff to be done in the background
});

Шаблон для очередей операций очень похож. Создайте очередь операций и добавьте операции в эту очередь.

На самом деле синхронное и асинхронное различие полностью отличается от различия между основной очередью и фоновой очередью. Но когда люди говорят о "медленном запуске процесса асинхронно", они действительно говорят: "Запускайте медленный процесс асинхронно в фоновом режиме".

Ответ 2

"Синхронный" по существу означает "по порядку". В принципе, когда вы выполняете синхронную операцию, все, что приходит позже, должно ждать завершения операции, прежде чем они смогут начать.

И наоборот, "асинхронный" более или менее означает "не в порядке". Когда вы делаете что-то асинхронно, следующий код может сразу запускаться, и асинхронная операция будет выполняться... когда-нибудь. Он может запускаться параллельно с остальной частью кода в другом потоке. Это может быть просто запланировано на какое-то другое время в одном и том же потоке.

Понятие синхронности не имеет ничего общего с конкретными потоками. Это просто о том, нужно ли ждать завершения операции или нет.

Там, где основной поток вступает в это в большой степени, это программы Cocoa (Touch). AppKit запускает основной цикл событий в основном потоке, поэтому, если основной поток ожидает завершения операции, он не может обрабатывать какие-либо ввод или обновлять пользовательский интерфейс. Если у вас есть часть кода, работающая на фоновом потоке, хотя запуск синхронного кода не будет блокировать цикл основного события, потому что это не основной поток, ожидающий завершения синхронной операции.

Аналогичным образом, длительная асинхронная операция из фонового потока, который вы помещаете в основной поток, может вызвать проблемы, поскольку в то время как фоновый поток не ждет завершения операции, он по-прежнему занимает основное время в основном потоке где цикл события должен быть запущен.

Ответ 3

Позвольте нам сделать несколько простых примеров:

Асинхронный вызов с многопоточным:

// Methods gets called in different thread and does not block the current thread. 
[NSURLConnection sendAsynchronousRequest:request 
                                   queue:queue 
                       completionHandler:
    ^(NSURLResponse *response, NSData *data, NSError *error) {
}];

Синхронный вызов с использованием многопоточности:

//Do something
dispatch_sync(queue, ^{
    //Do something else
});
//Do More Stuff

Здесь вы получили//Делаем что-то//Делаем что-то еще и//Делаем больше вещей, выполняемых последовательно, хотя//Делаем что-то еще в другом потоке.

Обычно, когда люди используют другой поток, вся цель заключается в том, что что-то можно выполнить без ожидания. Предположим, вы хотите загрузить большой объем данных, но хотите, чтобы пользовательский интерфейс был гладким.

Следовательно, dispatch_sync редко используется. Но это там. Я лично никогда не использовал это. Почему бы не попросить пример кода или проекта, который использует dispatch_sync.

Асинхронный вызов с одним потоком:

[self performSelector:@selector(doSomething) withObject:nil afterDelay:0];

Здесь вызывается текущая runloop до вызова doSomething. Другими словами, текущий стек вызовов может быть завершен (текущий метод возвращается) до вызова "doSomething".

Синхронный вызов с одним потоком:

 [self doSomething];

Я не думаю, что для этого вам нужны объяснения.

В общем, асинхронная активность не такая же, как потоки, однако в iOS они реализованы с использованием этого способа. Это не соответствует всем языкам. Обычно мы используем различные асинхронные задачи с использованием циклов запуска.

Ответ 4

Асинхронный означает "вне линии", синхронные средства в очереди. Вы можете выполнять синхронные задачи и блокировать сразу несколько потоков.

Если вы находитесь в фоновом потоке и хотите обновить целую кучу пользовательского интерфейса, вы вызываете основной поток в очереди dispatch. Если вы вызове dispatch_sync то код, который вы в настоящее время ожидаете, завершает dispatch, тем самым блокируя фоновый поток, в котором вы находитесь, и блокируя пользовательский интерфейс, когда он обновляет основной поток.

Но если вы вызвали dispatch_async фоновый поток продолжился бы с остальной частью указанного кода, а основной поток выполнил бы запрошенный блок dispatch.

То же самое можно сказать и в основном потоке. если вы вызываете dispatch_sync из основного потока в глобальную или пользовательскую очередь, он блокирует основной поток, пока он запускает код в отдельном потоке. Я не могу сказать, что знаю случай, когда это будет использоваться, но это, безусловно, возможно.

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

Синхронное средство блокировки, асинхронное означает, что оно будет завершено позднее (возможно, прямо сейчас), не блокируя то, что вы сейчас делаете.

Ответ 5

Это обсуждение в значительной степени отвечает на это: Асинхронный против многопоточности - есть ли разница?

В общем случае асинхронный вызов не обязательно создает новый поток. Это один из способов его реализации, поскольку существующий пул потоков или внешний процесс являются другими способами. Это сильно зависит от языка, объектной модели (если есть) и среды времени выполнения.

Асинхронный просто означает, что вызывающий поток не сидит и не ждет ответа, и асинхронная активность не происходит в вызывающем потоке.

Таким образом, в основном, другие действия могут произойти в ожидании загрузки чего-либо, но это может быть или не быть сделано в отдельных потоках.

Ответ 6

swift 3, 4, 4,2 Синхронный означает, что поток, инициировавший эту операцию, будет ждать завершения задачи перед продолжением.

DispatchQueue.main.sync {

}

Асинхронный означает, что Завершение задачи в фоновом режиме и может уведомить вас по завершении означает, что она не будет ждать.

DispatchQueue.main.async {

}

Ответ 7

Синхронный: ожидает выполнения задачи
выполнитьBlockAndWait, является синхронным. Основной поток остановится и дождитесь ответа от блока, прежде чем он продолжит следующую операцию.

Асинхронный: завершает задачу в фоновом режиме и может уведомить вас по завершении.
executeBlock, метод является асинхронным. Это означает, что он может работать в любое время, и вызываемая им функция может продолжаться без необходимости знать, был ли блок успешным или нет. Основной поток может продолжаться, даже если блок по-прежнему или даже не запускался.