Channel Synchronization in Erlang

We can use processes and messages to synchronize execution across concurrent tasks in Erlang. 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 a supervision tree or other OTP behaviors.

-module(channel_synchronization).
-export([start/0]).

% This is the function we'll run in a separate process. The
% Parent process PID will be used to notify the main process
% that this function's work is done.
worker(Parent) ->
    io:format("working..."),
    timer:sleep(1000),
    io:format("done~n"),
    % Send a message to notify that we're done.
    Parent ! done.

start() ->
    % Start a worker process, giving it our PID to notify on.
    spawn(fun() -> worker(self()) end),
    
    % Block until we receive a notification from the
    % worker process.
    receive
        done -> ok
    end.

To run the program:

$ erl
1> c(channel_synchronization).
{ok,channel_synchronization}
2> channel_synchronization:start().
working...done
ok

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

In Erlang, we use processes instead of goroutines, and message passing instead of channels. The spawn/1 function is used to create a new process, and the ! operator is used to send messages between processes. The receive construct is used to wait for and handle incoming messages.

The timer:sleep/1 function is used to simulate work being done, similar to time.Sleep in the original example.

This example demonstrates a simple form of process synchronization in Erlang, which is conceptually similar to the channel synchronization shown in the original example.