it-swarm.com.ru

В чем разница между синхронными и асинхронными вызовами в Objective-C и многопоточностью?

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

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

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

50
Doug Smith

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

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

Итак, есть две части этого. Во-первых, используя 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
});

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

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

101
Rob

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

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

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

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

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

27
Chuck

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

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

 // Методы вызываются в другом потоке и не блокируют текущий поток. [.__ }];. 

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

 // Делаем что-то 
 Dispatch_sync (queue, ^ {
 // Делаем что-то еще 
}); 
 // Делаем больше материала 
 

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

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

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

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

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

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

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

 [self doSomething]; 

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

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

16
Kunal Balani

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

DispatchQueue.main.sync {

}

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

DispatchQueue.main.async {

}
4
akbar khan

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

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

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

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

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

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

3
Putz1103

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

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

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

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

2
mjdth