Un atelier Rust · Édition d'ApprentissageA Rust Workshop · Learning Edition

Les canaux, ou share memory by communicating Channels, or share memory by communicating

Passer des messages plutôt que partager de la mémoire : la possession transférée par le canal. Plus rien à partager, donc plus de course — par construction, pas par verrou. Pass messages rather than share memory: ownership transferred through the channel. Nothing left to share, hence no race — by construction, not by lock.

AudienceAudience
Dev maîtrisant possession, threads et Arc<Mutex> (Vol 1, Vol 7 №1–2) Dev fluent in ownership, threads and Arc<Mutex> (Vol 1, Vol 7 №1–2)
Format
Self-paced
ChapitresChapters
5
Date
Juin 2026 Jun 2026
≈ 19 min ●●●○ ConcurrenceCanauxmpsc

Chapitre 1 en accès libre — la suite (ch. 2 à 5) est réservée. Chapter 1 free to read — the rest (ch. 2–5) is members-only.

01CadrageFraming3 min

Et si la difficulté venait du partage — qu'on cesserait alors de partager ?What if the difficulty came from sharing — which we'd then stop doing?

Le numéro précédent a rouvert le partage mutable, mais au prix d'un verrou, d'une contention à doser et d'un deadlock qu'aucune preuve ne couvre. C'est le terrain difficile de la concurrence — et il le reste, même en Rust. Les canaux retournent le problème au lieu de l'affronter : plutôt que plusieurs threads se disputant une même mémoire mutable, un thread envoie un message, un autre le reçoit. La devise, empruntée à Go et faite sienne par Rust : « ne communique pas en partageant la mémoire ; partage la mémoire en communiquant ». Et le mécanisme qui rend cela sûr, on le connaît déjà : la possession de la donnée est déplacée à travers le canal — le move du Vol 1. L'émetteur la perd, le récepteur la gagne. À aucun instant deux threads ne la tiennent ensemble. Le data race n'est pas interdit : il devient impossible à exprimer, parce qu'il n'y a plus rien à partager.The previous issue reopened shared mutation, but at the price of a lock, of contention to balance, and of a deadlock no proof covers. That's concurrency's hard ground — and it stays hard, even in Rust. Channels flip the problem instead of fighting it: rather than several threads contending over the same mutable memory, one thread sends a message, another receives it. The motto, borrowed from Go and made Rust's own: 'don't communicate by sharing memory; share memory by communicating'. And the mechanism that makes this safe, we already know: ownership of the data is moved through the channel — Vol 1's move. The sender loses it, the receiver gains it. At no instant do two threads hold it together. The data race isn't forbidden: it becomes inexpressible, because there's nothing left to share.

La possession entre par send(), ressort par recv()Ownership enters via send(), exits via recv()
thread émetteursender thread
message: String
possèdeowns
send(msg) ▸move : entremove: in
canalchannel
≋≋≋
FIFO
▸ recv()move : sortmove: out
thread récepteurreceiver thread
recu: String
possèdeowns
Le canal, en un aller simpleThe channel, in one one-way trip
use std::sync::mpsc;
use std::thread;

let (tx, rx) = mpsc::channel();           // tx : l'émetteur · rx : le récepteur

thread::spawn(move || {
    let message = String::from("résultat");
    tx.send(message).unwrap();            // la possession de `message` ENTRE dans le canal
});                                       // (move : ce thread possède tx et message)

let recu = rx.recv().unwrap();            // …et RESSORT ici, côté récepteur
println!("{recu}");                       // un seul propriétaire à tout instant : rien n'est partagé

mpsc::channel() rend une paire : un émetteur (tx) et un récepteur (rx). send dépose une valeur dans le canal, recv la retire de l'autre côté. Ce qui circule n'est pas une référence partagée mais la valeur elle-même, dont la possession voyage. Compare au Arc<Mutex> du №2 : là, plusieurs threads pointaient vers une mémoire commune et se relayaient par un verrou ; ici, la donnée n'est jamais commune — elle passe de main en main, et une seule main la tient à la fois.mpsc::channel() returns a pair: a sender (tx) and a receiver (rx). send drops a value into the channel, recv pulls it out the other side. What flows isn't a shared reference but the value itself, whose ownership travels. Compare to №2's Arc<Mutex>: there, several threads pointed at common memory and took turns via a lock; here, the data is never common — it passes hand to hand, and only one hand holds it at a time.

Le réflexe du numéroThe issue's reflex

« Avant de dégainer Arc<Mutex>, ai-je vraiment besoin de partager — ou puis-je transférer la possession par un message ? » Quand des threads se passent du travail (une file de tâches, un pipeline, des résultats à collecter), le canal est presque toujours plus simple et plus sûr que la mémoire partagée : pas de verrou, pas de section critique, pas de deadlock sur des données. On ne synchronise pas l'accès — on supprime le besoin de synchroniser.'Before reaching for Arc<Mutex>, do I truly need to share — or can I transfer ownership through a message?' When threads hand off work (a task queue, a pipeline, results to collect), the channel is almost always simpler and safer than shared memory: no lock, no critical section, no deadlock on data. You don't synchronize access — you remove the need to synchronize.

mpsc : ce que disent les quatre lettresmpsc: what the four letters say

multi-producer, single-consumer. Plusieurs émetteurs peuvent alimenter le même canal (l'émetteur se clone) ; un seul récepteur en sort les messages. C'est le canal de la std, dans std::sync::mpsc. Le modèle couvre l'immense majorité des cas : N ouvriers qui rapportent à un collecteur. Pour plusieurs récepteurs (multi-consumer) ou des canaux plus rapides, on nommera crossbeam au chapitre 3 — mais le réflexe et la sûreté sont identiques.multi-producer, single-consumer. Several senders can feed the same channel (the sender clones); one receiver pulls the messages out. It's the std's channel, in std::sync::mpsc. The model covers the vast majority of cases: N workers reporting to one collector. For several receivers (multi-consumer) or faster channels, we'll name crossbeam in chapter 3 — but the reflex and the safety are identical.

🔒

La suite est réservée The rest is members-only

Le premier numéro est libre. Débloque tout The Rust Loop — tous les volumes, à vie — pour 5 €, paiement unique. The first issue is free. Unlock all of The Rust Loop — every volume, forever — for €5, one-time.

Retour au kiosqueBack to newsstand