Entiendo más o menos lo síncrono y lo asíncrono, pero todo se complica cuando aparecen los términos bloqueante y no bloqueante.
En el artículo relacionado Proceso vs. hilo: la pregunta n.º 1 de las entrevistas técnicas, explicada con la estructura de memoria puedes repasar los conceptos básicos y los casos de aplicación relacionados. Dispatch
Puede parecer que “síncrono = bloqueante y asíncrono = no bloqueante”, pero son ejes distintos. Al combinarlos aparecen cuatro casos, y los cuatro existen en la práctica.
Estos conceptos aparecen al hablar de código de red, async/await o bucles de eventos como los de Node.js. Cuando entiendes bien los ejes, puedes reutilizar este conocimiento una y otra vez.
En este artículo se distinguen con precisión los dos ejes y se explican las cuatro combinaciones 2×2 con ejemplos.
Empecemos con el resumen clave.
- Eje síncrono/asíncrono: quién controla la finalización — es síncrono si la controla directamente quien llama y asíncrono si recibe una notificación
- Eje bloqueante/no bloqueante: si el control se devuelve inmediatamente al llamar — si no se devuelve, es bloqueante; si se devuelve de inmediato, no bloqueante
- Los dos ejes son independientes, por lo que existen las 2×2 = 4 combinaciones
- En la práctica, las dos combinaciones más habituales son síncrono + bloqueante y asíncrono + no bloqueante
Eje 1: Síncrono vs. asíncrono — ¿quién controla la finalización?
Síncrono significa que quien llama controla directamente si una tarea ha terminado. Tras enviar una solicitud, el flujo queda ligado a esa tarea hasta que llega el resultado.
Cuando termina A, se ejecuta B; cuando termina B, se ejecuta C. El orden está garantizado.
Asíncrono significa enviar una solicitud, continuar con otro trabajo y recibir una notificación cuando termina. Los callbacks, los cierres y las continuations de async/await son ese “canal de notificación” (POSIX aio_read).
Pensemos en un restaurante. Lo síncrono es pedir y esperar delante del mostrador hasta que salga la comida.
Lo asíncrono es recibir un avisador, hacer otra cosa en la mesa y recoger la comida cuando suene.
Eje 2: Bloqueante vs. no bloqueante — ¿se devuelve el control?
Aquí cambia la perspectiva. El criterio es si la función llamada devuelve el control de inmediato.
Bloqueante significa que, tras la llamada, el hilo que llama queda ocupado hasta que termina la función. Durante ese tiempo no puede hacer nada más.
No bloqueante significa que la llamada retorna inmediatamente. Si el resultado aún no está listo, devuelve incluso un estado como “todavía no está listo” (POSIX read).
Si síncrono/asíncrono describe la “gestión de la finalización”, bloqueante/no bloqueante describe la “espera”. Son ejes diferentes.
Todas las combinaciones 2×2
| Combinación | Comportamiento | Ejemplo representativo |
|---|---|---|
| Síncrono + bloqueante | Esperar el resultado y continuar después | Llamada a una función normal, lectura básica de archivos |
| Síncrono + no bloqueante | Retornar de inmediato y comprobar repetidamente si está listo (sondeo) | Socket no bloqueante comprobado continuamente en un bucle |
| Asíncrono + bloqueante | Esperar la notificación mientras el hilo queda ocupado | Iniciar una API asíncrona y esperar inmediatamente su resultado |
| Asíncrono + no bloqueante | Lanzarlo, hacer otro trabajo y recibir una notificación al terminar | Callback de URLSession, async/await |
El síncrono + no bloqueante puede resultar extraño: es como “un cliente que va al mostrador cada minuto a preguntar «¿ya está listo?» sin avisador”.
Conserva el control, pero controla la finalización por sí mismo; por eso es síncrono.
Asíncrono + bloqueante es, en la práctica, una combinación poco útil. Si haces algo asíncrono pero esperas inmediatamente el resultado, no difiere de síncrono + bloqueante y solo añade complejidad.
El código que llama a wait justo después de iniciar una función asíncrona es un ejemplo de este caso.
En Swift
La terminología sync/async de la época de GCD (Grand Central Dispatch) se acerca más a describir si hay bloqueo.
queue.sync mantiene ocupado el hilo actual hasta que termina su cierre (bloqueante). queue.async envía el trabajo y pasa directamente a la siguiente línea (no bloqueante).
async/await es una sintaxis que hace que el código asíncrono + no bloqueante se lea como código síncrono.
let data = try await fetchImage() // Aquí se «suspende»
// El hilo no queda bloqueado y pasa a hacer otro trabajo
En el punto await, la función se pausa brevemente, pero el hilo queda libre para procesar otro trabajo. El código se lee de arriba abajo como código síncrono, aunque su comportamiento real es no bloqueante.
“No bloquear el hilo principal y escribir de forma secuencial sin caer en el infierno de callbacks” es la razón de existir de esta sintaxis.
Puntos clave para entrevistas
El comienzo consiste en distinguir los criterios de los dos ejes con una frase para cada uno.
“Bloqueante/no bloqueante trata sobre si el control se devuelve de inmediato, mientras que síncrono/asíncrono trata sobre si quien llama controla la finalización o recibe una notificación.”
Después, ante la pregunta de seguimiento “da un ejemplo de las cuatro combinaciones”, basta con presentar uno por uno los casos de la tabla. Poder explicar síncrono + no bloqueante (sondeo) demuestra especialmente que entiendes los ejes.
Resumen
- Síncrono/asíncrono: es síncrono si quien llama controla directamente la finalización y asíncrono si recibe una notificación
- Bloqueante/no bloqueante: es bloqueante si no devuelve el control al llamar y no bloqueante si lo devuelve de inmediato
- Los dos ejes son independientes, por lo que existen las cuatro combinaciones
- Síncrono + no bloqueante es sondeo; asíncrono + bloqueante suele ser una combinación poco útil
- El sync/async de GCD se acerca más a describir el bloqueo, mientras que async/await hace que el código asíncrono + no bloqueante se lea como código síncrono
- Metáfora del restaurante: esperar en el mostrador (síncrono + bloqueante), preguntar cada minuto (síncrono + no bloqueante) y usar un avisador (asíncrono + no bloqueante)
Fuentes y criterios de verificación
- POSIX read — The Open Group · texto original del estándar/especificación · comprobado 2026-08-17 · fundamento: E/S bloqueante y comportamiento de O_NONBLOCK
- POSIX aio_read — The Open Group · texto original del estándar/especificación · comprobado 2026-08-17 · fundamento: solicitudes de E/S asíncronas y modelos de finalización
- Dispatch — Apple · documentación oficial · comprobado 2026-08-17 · fundamento: envío de tareas síncronas y asíncronas basado en colas

