Channel Synchronization in Crystal
Channel synchronization is a powerful feature for coordinating execution across fibers. Here’s an example of using a blocking receive to wait for a fiber to finish. When waiting for multiple fibers to finish, you may prefer to use a Channel(Nil)
.
require "fiber"
# This is the function we'll run in a fiber. The
# `done` channel will be used to notify another
# fiber that this function's work is done.
def worker(done : Channel(Bool))
print "working..."
sleep 1
puts "done"
# Send a value to notify that we're done.
done.send(true)
end
# Start a worker fiber, giving it the channel to
# notify on.
done = Channel(Bool).new(1)
spawn worker(done)
# Block until we receive a notification from the
# worker on the channel.
done.receive
To run the program:
$ crystal run channel_synchronization.cr
working...done
If you removed the done.receive
line from this program, the program would exit before the worker
even started.
In Crystal, we use spawn
to create a new fiber, which is similar to a lightweight thread. The Channel
class is used for communication between fibers, allowing them to pass messages and synchronize their execution.
The worker
function simulates some work by sleeping for a second, then sends a true
value on the done
channel to signal that it has finished.
In the main fiber, we create a buffered channel with a capacity of 1, start the worker fiber, and then wait for it to finish by receiving from the done
channel. This receive operation blocks until a value is sent on the channel, effectively synchronizing the main fiber with the worker fiber.
This pattern is useful for ensuring that background tasks complete before the program exits, or for coordinating multiple concurrent operations.