¿Cuál es la diferencia entre las llamadas síncronas y asincrónicas en Objective-C, frente a las multithreading?

Durante mucho tiempo, pensé que también era asíncrono ejecutar algo en un hilo de fondo, mientras que sincrónico significaba en el hilo principal (locking de actualizaciones e interacciones de UI). Entiendo que no ejecutar el hilo principal para acciones costosas es porque no permite que ocurran acciones de IU ya que el hilo principal está ocupado, pero ¿por qué es problemático sincrónico?

Sin embargo, desde entonces me llamó la atención que puede realizar llamadas asincrónicas en el hilo principal y llamadas síncronas en los hilos de fondo.

Siempre escucho a personas que dicen que no deben usar costosas llamadas de forma síncrona o en el hilo principal, ya que bloqueará la interfaz de usuario para el usuario. ¿Estos dos problemas separados debo asegurarme de que no lo haga? ¿Cuáles son las diferencias?

Cuando invocas algo sincrónicamente, significa que el hilo que inició esa operación esperará a que la tarea finalice antes de continuar. Asíncrono significa que no esperará.

Dicho esto, cuando las personas sugieren que realice algún proceso lento o costoso de forma asincrónica, sugieren implícitamente no solo que debe ejecutarlo de forma asincrónica, sino que debe hacerlo en un hilo de fondo. El objective es liberar el hilo principal para que pueda seguir respondiendo a la interfaz de usuario (en lugar de congelarse), por lo que está enviando tareas a un hilo de fondo de forma asincrónica.

Entonces, hay dos partes para eso. Primero, usando GCD como ejemplo, tomas una cola de fondo (o tomas una de las colas de fondo globales, o creas la tuya):

// 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); 

En segundo lugar, envía sus tareas a esa cola de forma asincrónica:

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

El patrón para colas de operación es muy similar. Cree una cola de operación y agregue operaciones a esa cola.

En realidad, la distinción síncrona vs asincrónica es completamente diferente de la distinción cola principal frente a fila de fondo. Pero cuando la gente habla de “ejecutar un proceso lento de forma asincrónica”, realmente están diciendo “ejecutar un proceso lento de forma asincrónica en una cola de fondo”.

“Sincrónico” significa esencialmente “en orden”. Básicamente, cuando realiza una operación sincrónica, todo lo que viene después debe esperar a que la operación finalice para poder comenzar.

Por el contrario, “asincrónico” significa más o menos “no en orden”. Cuando hace algo asincrónicamente, el siguiente código se puede ejecutar inmediatamente y la operación asincrónica se ejecutará … en algún momento. Puede ejecutarse en paralelo con el rest del código en otro hilo. Podría simplemente progtwigrse para otro momento en el mismo hilo.

El concepto de sincronicidad no tiene nada que ver con hilos en particular, per se. Solo se trata de si tiene que esperar a que finalice una operación o no.

Donde el hilo principal entra en esto a lo grande es en los progtwigs Cocoa (Touch). El AppKit ejecuta el bucle de evento principal en el hilo principal, por lo que si el hilo principal está esperando que se complete una operación, no puede procesar ninguna entrada ni actualizar la interfaz de usuario. Sin embargo, si tiene un trozo de código ejecutándose en una cadena de fondo, ejecutar código síncrono no bloqueará el bucle de evento principal , porque no es el hilo principal que está esperando que se complete la operación síncrona.

Del mismo modo, una operación asincrónica de larga ejecución desde un hilo de fondo que coloque en el hilo principal puede causar problemas, porque aunque el hilo de fondo no va a esperar a que la operación se complete, todavía está tomando tiempo en el hilo principal donde el ciclo de eventos necesita ejecutarse.

Permite tomar algunos ejemplos fáciles:

Llamada asincrónica con multihilo:

 // Los métodos se llaman en diferentes subprocesos y no bloquean el subproceso actual. 
 [NSURLConnection sendAsynchronousRequest: solicitud 
                                    cola: cola 
                        FinalizadorHandler:
     ^ (NSURLResponse * response, NSData * data, NSError * error) {
 }];

Llamada síncrona con multihilo:

 //Hacer algo
 dispatch_sync (cola, ^ {}
     //Hacer algo más
 });
 // Haz más cosas

Aquí tienes // Haz algo // Haz otra cosa y // Haz más cosas de forma consecutiva, aunque // Hagas otra cosa en un hilo diferente.

Usualmente, cuando las personas usan diferentes hilos, el propósito es que algo se pueda ejecutar sin esperar. Supongamos que desea descargar una gran cantidad de datos pero desea mantener la interfaz de usuario sin problemas.

Por lo tanto, dispatch_sync se usa raramente. Pero está ahí. Yo personalmente nunca usé eso. ¿Por qué no solicitar un código de muestra o proyecto que sí utiliza dispatch_sync?

Llamada asincrónica con un hilo:

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

Aquí se ejecuta el runloop actual antes de ‘doSomething’. En otras palabras, la stack de llamadas actual puede completarse (el método actual vuelve) antes de que se llame a ‘doSomething’.

Llamada síncrona con un hilo:

  [self doSomething];

No creo que necesites una explicación para esto.

En general, la actividad asíncrona no es lo mismo que enhebrar, sin embargo, en iOS se implementan de esta manera. No es cierto para todos los idiomas. Por lo general, administramos diferentes tareas asincrónicas utilizando ciclos de ejecución.

Asincrónico significa fuera de línea, sincrónico significa en línea. Puede realizar tareas sincrónicas y bloquear múltiples hilos a la vez.

Si está en un hilo de fondo y desea actualizar un montón de la interfaz de usuario, llame al hilo principal en una cola de dispatch . Si llama a dispatch_sync entonces el código en el que se encuentra actualmente espera a que finalice el dispatch , bloqueando así el hilo de fondo en el que se encuentra y bloqueando la interfaz de usuario mientras actualiza el hilo principal.

Pero si llama a dispatch_async el hilo de fondo continuará con el rest del código listado y el hilo principal ejecutará el bloque de dispatch solicitado.

Lo mismo puede decirse cuando en el hilo principal. si llama a un dispatch_sync desde el hilo principal en una cola global o personalizada, bloqueará el hilo principal mientras ejecuta el código en un hilo separado. No puedo decir que conozco un caso en el que se usaría eso, pero seguramente es posible.

Siempre que tenga código de cálculo, código de servicio web, código de recuperación, lo que no afecte a la UI, es mejor hacerlo en un hilo separado. Para este tipo de cosas, haría un dispatch_async en un hilo global. Luego, cuando se complete ese código, ejecutaría un dispatch_async en el hilo principal para indicarle que actualice la UI con lo que acabo de calcular.

Sincrónico significa locking, asíncrono significa que se completará en un momento posterior (tal vez ahora) sin bloquear lo que está haciendo actualmente.

Esta discusión prácticamente lo responde: asincrónico vs multihilo: ¿hay alguna diferencia?

En el caso general, una llamada asincrónica no crea necesariamente un nuevo hilo. Esa es una forma de implementarlo, con un grupo de subprocesos preexistente o un proceso externo de otras maneras. Depende en gran medida del idioma, el modelo de objeto (si lo hay) y el entorno de tiempo de ejecución.

Asíncrono solo significa que el hilo que llama no se sienta y espera la respuesta, ni tampoco ocurre la actividad asincrónica en el hilo de llamada.

Entonces, básicamente, otras actividades pueden suceder mientras se espera que algo se cargue, pero puede o no hacerse en hilos separados.

swift 3, 4, 4,2 Sincrónico significa que el hilo que inició esa operación esperará a que la tarea finalice antes de continuar.

 DispatchQueue.main.sync { } 

Asíncrono significa que completa una tarea en segundo plano y puede avisarte cuando esté completo significa que no esperará.

 DispatchQueue.main.async { } 

Sincrónico : espera hasta que la tarea se haya completado
performBlockAndWait, es sincrónico. El hilo principal se detendrá y esperará una respuesta del bloque antes de continuar con la siguiente operación.

Asincrónico : completa una tarea en segundo plano y puede avisarte cuando esté completa.
performBlock, método es el que es asincrónico. Eso significa que puede ejecutarse en cualquier momento y la función que lo llamó puede continuar sin necesidad de saber si el locking fue exitoso o no. El hilo principal puede continuar incluso si el bloque está quieto o no comenzó a funcionar.