Ejemplos concretos
Me gustaría agregar algunos ejemplos del mundo real y conectarlos al mundo de la ingeniería de software. Primero, considere algo que espero coincida con su definición intuitiva de "sincrónico": el parpadeo de las luciérnagas , en algunas circunstancias. En segundo lugar, considere la carrera de relevos olímpicos femeninos 4x100 . Tercero, considere ese viejo tropo de las películas militares: "¡Hombres, sincronicen sus relojes!"
Ahora, pensemos en lo que está pasando. Comencemos observando que todas estas cosas son procesos o entidades extendidas en el tiempo . No tiene sentido decir que un cuenco es "sincrónico" y que el rock es "asíncrono". Segundo, se necesitan dos para bailar tango . No se puede decir que "un corredor es sincronización". ¿Sincronizar con qué? Finalmente, para que dos procesos hagan algo al mismo tiempo, a menos que ya tengan exactamente la misma frecuencia y fase, uno o ambos deben esperar .
Análisis
Cuando la definición del diccionario dice que dos entidades sincronizadas "ocurren o existen al mismo tiempo", eso se alinea muy bien con el concepto de la luz de las luciérnagas. Desafortunadamente, decir que la luz está "sincronizada" es una manera descuidada de decir que los procesos de iluminación de la luciérnaga están sincronizados.
Entonces, ¿cómo pueden un montón de luciérnagas, que presumiblemente no tienen Apple SmartWatch y NTP para guiarlos, lograr flashear sus extremos traseros al mismo tiempo? Bueno, es bastante fácil si tienen un medio para establecer un tempo constante y pueden hacer pequeños ajustes. Simplemente parpadean, y si más personas parpadean justo después de ellos, disminuyen la velocidad (aumentan el retraso), mientras que si parpadean más justo antes de ellos, se aceleran (disminuyen el retraso). Entonces pueden usar un proceso de retroalimentación simple para llegar esencialmente al mismo tempo y fase. La observación importante aquí es notar que logran sincronía al esperar el momento adecuado para destellar .
La carrera 4x100 es interesante porque ves ambas formas de sincronización del proceso en acción: los corredores dentro de un equipo están sincronizados, mientras que los corredores en diferentes equipos están "asíncronos". El segundo corredor en el relevo debe esperar hasta que el primer corredor entre en la zona de transferencia . La transferencia es un evento síncrono entre esos dos corredores. Sin embargo, a los corredores en diferentes carriles no les importa lo que está sucediendo en otro carril , y ciertamente no disminuyen la velocidad y hacen sus traspasos sincronizados. Cada carril de corredores es asíncrono uno con respecto al otro. Nuevamente, vemos que la sincronización implica esperar, mientras que la asincronía no.
Finalmente, los soldados en una compañía (pelotón, equipo de bomberos, etc.) deben sincronizar sus relojes para que puedan atacar al enemigo al mismo tiempo . Puede ser que algunos soldados lleguen a sus posiciones antes que otros, o tengan la oportunidad de disparar al enemigo antes. Pero un ataque simultáneo es generalmente más efectivo que un ataque fortuito debido al elemento sorpresa. Entonces, para lograr la sincronía, muchos de los soldados deben esperar el momento señalado para actuar.
Caracteristica que define
¿Por qué este énfasis en esperar? Bueno, es porque esperar es la característica definitoria que distingue los procesos síncronos de los asíncronos. Si tiene dos procesos de los que no sabe nada, debería, por defecto, asumir que son asíncronos. Por ejemplo, un paquete de entrega y una ambulancia conduciendo probablemente no estén sincronizados. Para demostrar que dos procesos están, de hecho, sincronizados, necesita encontrar un momento muy especial en el tiempo: el punto de sincronización .
Un conductor de entrega que deja un paquete y una ambulancia que lleva a alguien al hospital generalmente no comparten ningún punto en el tiempo que identifiquemos como "punto de sincronización". Por otro lado, las luciérnagas que parpadean al unísono tienen un punto de sincronización cada vez que parpadean, los corredores de relevos tienen un punto de sincronización cada vez que entregan el bastón y los soldados tienen un punto de sincronización cuando lanzan su ataque. Si puede identificar uno o más puntos de sincronización, los procesos se sincronizan . Esto debería ser fácil de entender, porque "syn-" es un prefijo griego que significa "con" o "juntos", y "chrono" es la raíz griega para "tiempo". "Sincronizado" significa literalmente "al mismo tiempo",
Límites
Tenga en cuenta que la "sincronización" no se aplica necesariamente a toda la vida útil de uno o ambos procesos. Yo diría que solo se aplica al "tiempo de espera hasta el punto o puntos de sincronización incluidos". Por lo tanto, dos procesos pueden funcionar de forma asíncrona hasta que alcanzan un estado en el que necesitan comunicarse, luego se sincronizan, intercambian información y luego continúan asincrónicamente. Un ejemplo simple es conocer a alguien para tomar un café. Obviamente, la reunión es un punto de sincronización (o muchos, más bien), y el hecho de que dos personas lleguen a ese punto demuestra la sincronía. Sin embargo, no diríamos que debido a que dos personas se reunieron para tomar café, esas dos vidas humanasestán "sincronizados". Puede ser que ese fue el único instante en sus vidas que conocieron, y todo lo demás que hacen es independiente.
Tampoco es el caso que las reuniones incidentales demuestren sincronía. Si dos extraños se cruzan en la calle, el hecho de que se encuentren en un lugar determinado en algún momento no prueba la sincronía. Tampoco el hecho de que una persona esté sentada en un banco esperando el autobús y otra pase por allí. Los procesos solo son sincrónicos cuando se encuentran con un propósito .
Conexión de software
Ahora, pensemos en una tarea fundamental en el software: leer de un archivo. Como probablemente sepa, el almacenamiento masivo suele ser de miles a millones de veces más lento que el caché o la memoria principal. Por esta razón, los sistemas operativos y las bibliotecas de lenguaje de programación generalmente ofrecen operaciones de E / S sincrónicas y asincrónicas. Ahora, incluso si su programa solo tiene un hilo único, debe pensar en el sistema operativo como un "proceso separado" para los propósitos de esta discusión.
Sincronización
Cuando realiza una "lectura de E / S sincrónica", su subproceso debe esperar hasta que los datos estén disponibles, momento en el que continúa. Esto es muy parecido a un corredor de relevos que le entrega el testigo al siguiente corredor, pero imagina un relevo con solo dos corredores recorriendo la pista, y el segundo corredor también pasa al primero.
En este caso, el hilo de su programa y el proceso de E / S del sistema operativo no están "sucediendo (actuando) al mismo tiempo", por lo que parece extraño decir que estos procesos están "sincronizados". ¡Pero esa es la forma incorrecta de verlo! Es como decir: "Los corredores en un equipo de relevos no están corriendo al mismo tiempo, por lo que no están sincronizados". De hecho, ambas afirmaciones están equivocadas! Los corredores en un equipo de relevos hacen y deben ejecutarse al mismo tiempo, pero sólo en un momento muy específico: el hand-off de la batuta. De hecho, ¡es solo este momento especial durante la carrera que nos convence de que los equipos de relevos están sincronizados para empezar! Si consideramos la solicitud y la respuesta de E / S como "el testigo",
Por otro lado, si pensamos en algo como el análisis de elementos finitos en una supercomputadora, vemos que miles de procesos deben funcionar de forma sincronizada para actualizar un estado global masivo. Incluso si algunos de los nodos completan su trabajo durante un paso de tiempo determinado antes que otros, todos deben esperar a que se complete el paso de tiempo porque los resultados se propagan a los vecinos a través del espacio. Este tipo de sincronización es como las luciérnagas: todos los actores realizan el mismo tipo de tarea.
Variedad de proceso
Por esta razón, podemos inventar algunos términos para ayudarnos a ver que están sucediendo tres tipos de cosas: "sincronía homogénea", "sincronía heterogénea" y "sincronía secuencial". Entonces, cuando los actores realizan la misma tarea simultáneamente (FEA, luciérnagas), son "homogéneos". Cuando realizan diferentes tareas simultáneamente (soldados corriendo vs. gateando vs. nadando hacia sus destinos, física vs. sonido vs. hilos de IA en un juego), son "heterogéneos". Cuando realizan tareas de una en una, son "secuenciales" (corredores de relevos, bloqueando E / S). Pueden parecer muy diferentes, pero comparten una propiedad esencial: todos los tipos de actores realizan algunas esperas para garantizar que todos lleguen al punto de sincronización al mismo tiempo. entre puntos de sincronización, o "realizar la misma acción" es irrelevante para la propiedad de sincronía.
Las canalizaciones de procesamiento en una GPU son síncronas porque todas deben terminar el marco juntas e iniciar un nuevo marco juntas. Son homogéneos porque están haciendo el mismo tipo de trabajo, y todos están activos juntos. Pero el bucle principal del juego de un servidor y los hilos de bloqueo de E / S que procesan la entrada remota son heterogéneos porque realizan tipos de trabajo muy diferentes, y algunos de los hilos de E / S no harán nada en absoluto, porque no todos Se utilizan las conexiones. Aun así, están sincronizados, porque deben compartir el estado atómicamente (un jugador no debe ver una actualización parcial del mundo del juego, ni el servidor debe ver solo un fragmento de la entrada del jugador).
Asíncrono
Ahora, consideremos una "lectura de E / S asíncrona". Cuando su programa envía una solicitud al sistema operativo para leer un poco de datos del almacenamiento, la llamada vuelve inmediatamente . Ignoremos las devoluciones de llamada y centrémonos en las encuestas. En general, el momento en que los datos están disponibles para su programa no corresponde a ningún punto especial en el tiempo en lo que respecta al hilo de su programa. Si su programa no está esperando explícitamente los datos, entonces el hilo ni siquiera sabrá exactamente cuándo ocurre ese momento. Solo descubrirá que los datos están esperando la próxima vez que verifiquen.
No hay un horario de reunión especial en el que el sistema operativo y el hilo del programa acuerden entregar los datos. Son como dos barcos que pasan en la noche. La asincronía se caracteriza por esta ausencia de espera.. Por supuesto, el hilo del programa a menudo terminará esperando la operación de E / S después de todo, pero no es necesario. Felizmente puede seguir haciendo otros cálculos mientras se produce la recuperación de E / S, y solo verificará más tarde cuando tenga un momento libre. Por supuesto, una vez que el sistema operativo termina de buscar datos, tampoco se queda esperando. Simplemente coloca los datos en un lugar conveniente y continúa con su negocio. En este caso, es como si el programa entregara el testigo al sistema operativo, y el sistema operativo aparece más tarde, deja caer el testigo en el suelo junto con los datos y sale de la pista. El programa puede o no estar esperando para recibir la transferencia.
Paralelismo
Cuando marcamos una función como "asíncrona" en el software, a menudo significa que queremos paralelismo . Pero recuerde que el paralelismo no implica sincronía . Las luciérnagas son un buen ejemplo, porque también exhibieron un comportamiento sincrónico y asincrónico. Mientras que la mayoría de las moscas aparecían al unísono, muchas estaban obviamente desafinadas con el resto del grupo y aparecían más al azar. Las moscas pueden haber estado actuando simultáneamente , pero no todas estaban sincronizadas .
Ahora, cuando marcamos algún código como "asíncrono", parece divertido, porque implica que el resto del código que no está tan marcado es "sincronización". ¿Y eso que significa? ¿No insistimos en que la "sincronización" requería dos para el tango? Pero, ¿qué pasa si estamos hablando de la ejecución de código en un solo hilo? En este caso, debemos dar un paso atrás y pensar en un programa como una secuencia de estados y transiciones entre esos estados. Una declaración en un programa provoca una transición de estado. Podemos considerarlo como un "microproceso" que comienza y termina con la declaración. Los puntos de secuencia definidos por el lenguaje son, de hecho, los puntos de sincronización de estos "microprocesos". Y así, podemos ver un solo subproceso,
La integridad del lenguaje de programación garantiza que las actualizaciones de estado no interfieran entre las declaraciones, y los puntos de secuencia definen límites a través de los cuales el compilador no puede realizar optimizaciones observables. Por ejemplo, el orden de evaluación de las expresiones dentro de una declaración puede ser indefinido o subespecificado, dando al compilador la libertad de optimizar la declaración de varias maneras. Pero para cuando comience la siguiente declaración, el programa debe estar en un estado bien definido, si el PL en sí es sólido.
Por ahora, debería estar claro lo que queremos decir con "asíncrono". Significa exactamente que el contrato implícito de sincronía dentro de un bloque de código está exento para el bloque asíncrono. Se permite actualizar el estado del programa de forma independiente, sin las garantías de seguridad que normalmente implica el modelo de cálculo secuencial (coherente, sincrónico). Por supuesto, esto significa que debemos tener especial cuidado de no destruir el estado del programa con inconsistencia. Esto generalmente significa que introducimos una sincronización limitada y explícita para coordinar con el bloque asíncrono. Tenga en cuenta que esto significa que el bloque asíncrono puede ser asíncrono y síncrono en diferentes momentos. Pero recordando que la sincronización simplemente indica la existencia de un punto de sincronización, no deberíamos tener problemas para aceptar esta noción.