El lenguaje Crystal combina la sintaxis elegante de Ruby con un modelo de concurrencia ligero y eficiente, inspirado en Go.
En lugar de hilos del sistema operativo, Crystal usa fibers, que permiten ejecutar múltiples tareas de forma concurrente dentro del mismo proceso.
Una fiber es una unidad ligera de ejecución gestionada por el runtime de Crystal (no por el sistema operativo).
Varias fibers pueden ejecutarse “en paralelo” sobre un solo hilo de sistema, haciendo que la concurrencia sea cooperativa y eficiente.
Se crean usando la palabra clave spawn:
spawn do
puts "Hola desde una fiber!"
end
puts "Hola desde el hilo principal!"
sleep 0.1
Salida posible:
Hola desde el hilo principal!
Hola desde una fiber!
El sleep al final evita que el programa termine antes de que la fiber se ejecute (las fibers corren de forma asíncrona).
Las fibers se comunican a través de channels, una abstracción segura para enviar y recibir mensajes sin necesidad de locks.
channel = Channel(String).new
spawn do
channel.send("Mensaje desde otra fiber")
end
puts channel.receive
Salida:
Mensaje desde otra fiber
Los Channel son tipados (Channel(Int32), Channel(String), etc.), y pueden usarse para coordinar tareas concurrentes.
Veamos un ejemplo más realista con varias fibers:
channel = Channel(Int32).new
# Productor
spawn do
5.times do |i|
puts "Produciendo #{i}"
channel.send(i)
sleep 0.2
end
channel.close
end
# Consumidor
spawn do
for value in channel
puts "Consumiendo #{value}"
end
end
sleep 2
Salida:
Produciendo 0
Consumiendo 0
Produciendo 1
Consumiendo 1
Produciendo 2
Consumiendo 2
Produciendo 3
Consumiendo 3
Produciendo 4
Consumiendo 4
Crystal no crea múltiples hilos del sistema por cada fiber.
Las fibers son gestionadas por el scheduler del runtime.
El modelo es asíncrono cooperativo: las fibers ceden el control cuando hacen operaciones de I/O o esperan datos.
Este enfoque reduce el costo de cambio de contexto y permite miles de fibers concurrentes sin overhead.
Crystal adopta el modelo CSP (Communicating Sequential Processes) de Go, pero mantiene la simplicidad y legibilidad de Ruby.
Es importante notar que Crystal 1.x usa un solo hilo del sistema (no hay paralelismo real entre núcleos).
Sin embargo, el equipo de Crystal está trabajando en soporte multithreaded para futuras versiones.
Esto significa que las fibers son ideales para:
- I/O concurrente (HTTP, base de datos, archivos).
- Operaciones asíncronas livianas.
- Pero no para tareas intensivas en CPU.
La concurrencia en Crystal es una de sus características más elegantes:
- Usa fibers para tareas concurrentes sin complicaciones.
- Permite comunicación segura con channels.
- Ofrece un modelo simple, escalable y eficiente.
Si disfrutás del enfoque de Go o Elixir, pero querés la sintaxis de Ruby y velocidad de C, Crystal es una alternativa brillante para explorar.
