Doing concurrency in ‘share by communicating’ style has been popularized by the Go community. It’s a valuable approach to concurrency in Rust too, however, one has to be aware of the different semantics of Rust vs Go channels when doing so.

Rust standard library’s mpsc channels are described in the docs as “multi-producer, single-consumer FIFO queue communication primitives”, consisting of a “Sender” and a “Receiver” end.

Both ends of a Rust channel can only be ‘owned’ by one thread at the time, however the “Sender” half can be “cloned”, and through such cloning the conceptual “sender” part of a channel can be shared among threads, which is how you do the “multi-producer, single-consumer” part…

Go channels seem to consist of a single value(or is it a reference?), and to behave like a “multi-producer, multi-consumer queue” that can be shared among “goroutines”.

By default, a Go channel has a 0 buffer size, meaning that any sending on it will block until the other end has received the message.

In the Rust standard library, we can choose between using the default channel, that comes with a Sender with an unlimited buffer and hence will never block sending, and the sync_channel that comes with a SyncSender that will block sending if the buffer is full.

In both languages, channels can be passed around inside messages sent on them. So one can send a message on a channel containing a sender, and then immediately start waiting for an answer(which is like making a “cross-thread procedure call” and waiting for the return value).

For using the current std::sync::mpsc channels in Rust, we can limit ourselves to a single heuristic:

Communicate by sharing (clones of) your Sender, and keep the Receiver to yourself.

However, some ‘examples’ are still in order…