Channel Synchronization in Elixir

We can use processes and messages to synchronize execution across different parts of our program. Here’s an example of using a blocking receive to wait for a process to finish. When waiting for multiple processes to finish, you may prefer to use tasks or agents.

defmodule ChannelSynchronization do
  def worker(parent) do
    IO.write("working...")
    :timer.sleep(1000)
    IO.puts("done")
    send(parent, :done)
  end

  def main do
    spawn(fn -> worker(self()) end)
    receive do
      :done -> :ok
    end
  end
end

ChannelSynchronization.main()

This is the function we’ll run in a separate process. The parent process ID will be used to notify the main process that this function’s work is done.

The worker function simulates some work by printing “working…”, sleeping for a second, and then printing “done”. After the work is complete, it sends a message to the parent process.

In the main function:

We start a worker process, giving it the current process ID to notify when it’s done.

We then use receive to block until we receive a notification from the worker process.

To run the program:

$ elixir channel_synchronization.exs
working...done

If you removed the receive block from this program, the program would exit before the worker even started.

In Elixir, we use processes and message passing for concurrency, which is similar to Go’s goroutines and channels. The spawn function is used to create a new process, and send and receive are used for inter-process communication.