17. Concurrencia

En la programación tradicional, la concurrencia es un dragón temible. Hilos que se pisan entre sí, estados compartidos que se corrompen, condiciones de carrera que aparecen un martes de cada tres… Clojure domestica a ese dragón. Al ser las variables inmutables por defecto, la mayoría de problemas de concurrencia simplemente no existen. Ya conoces atom para el estado mutable controlado. Aquí veremos más herramientas para cuando necesites que varios hilos trabajen al unísono.

future

Ejecuta código en otro hilo y te devuelve una promesa de resultado. Cuando lo necesites, consulta con deref o @. Si aún no ha terminado, esperará pacientemente.

(def resultado (future (Thread/sleep 1000) (+ 1 1)))
@resultado
;; 2 (espera a que termine si aún no ha acabado)

promise

Una promesa es como enviar a Sancho a buscar provisiones: sabes que volverá con algo, pero no sabes cuándo. deliver le asigna el valor cuando llega, deref espera a que regrese.

(def p (promise))
(future (deliver p 42))
@p
;; 42

pmap

Como map, pero cada elemento se procesa en un hilo diferente. Es como tener varios escuderos trabajando a la vez en lugar de uno solo. Solo merece la pena cuando la función es costosa, si la operación es rápida el coste de coordinar hilos supera al beneficio.

(pmap #(do (Thread/sleep 100) (* % %)) [1 2 3 4 5])
;; (1 4 9 16 25) (se ejecutan en paralelo, más rápido que map)

Resumen

  • La inmutabilidad de Clojure elimina la mayoría de problemas de concurrencia.

  • atom para estado compartido sencillo (ya visto en el capítulo 7).

  • future ejecuta código en otro hilo.

  • promise es un contenedor de un solo uso.

  • pmap paraleliza map para operaciones costosas.

Ejercicios

  1. Usa future para simular 3 peticiones que tardan 1 segundo cada una. Recoge los resultados.

  2. Usa pmap para calcular el cuadrado de los números del 1 al 10 en paralelo.

Este trabajo está bajo una licencia Attribution-NonCommercial-NoDerivatives 4.0 International.

¿Me invitas a un café?

Visitantes en tiempo real

Estás solo: 🐱