crossbeam
23 Feb 2026Rust gives you threads in the standard library. It also gives you std::sync::mpsc. For simple programs, that might
be enough.
But once you start writing serious concurrent code, you quickly run into limitations:
std::sync::mpscis single-producer (despite the name).- Scoped threads are awkward.
- Lock-free structures are not in std.
- Performance characteristics are conservative.
crossbeam fills that gap.
It provides fast, well-designed concurrency primitives without inventing a runtime.
No async.
No executors.
Just threads done properly.
What Problem Does crossbeam Solve?
Two major ones:
- Better channels.
- Safe scoped threads.
Plus a toolbox of lock-free and memory-ordering utilities if you need them.
Unlike Tokio, Crossbeam is about native threads — not async tasks.
It embraces OS threads, but makes them less painful.
Minimal Example: Multi-Producer, Multi-Consumer Channel
The standard library’s channel has limitations.
Crossbeam’s channel is:
- Multi-producer
- Multi-consumer
- Fast
- Flexible (bounded or unbounded)
Cargo.toml
[package]
name = "crossbeam_demo"
version = "0.1.0"
edition = "2021"
[dependencies]
crossbeam = "0.8"main.rs
use crossbeam::channel;
use std::thread;
use std::time::Duration;
fn main() {
let (tx, rx) = channel::unbounded();
for i in 0..4 {
let tx = tx.clone();
thread::spawn(move || {
tx.send(format!("worker {i} done")).unwrap();
});
}
drop(tx); // close the channel
for msg in rx.iter() {
println!("{msg}");
}
}All workers send into the same channel.
Multiple producers.
Single consumer here — but you could clone rx too.
That’s already more flexible than std::sync::mpsc.
Bounded Channels (Backpressure)
Unbounded channels are convenient — but sometimes dangerous.
Crossbeam supports bounded channels:
let (tx, rx) = channel::bounded(2);If the channel fills up, send() blocks until space is available.
That gives you real backpressure.
This matters in systems code.
It prevents silent memory growth.
What’s Actually Happening?
Crossbeam channels are built for high performance and low contention.
Key design traits:
- MPMC (multi-producer, multi-consumer)
- Blocking and non-blocking operations
select!support- Efficient wakeups
You also get:
try_sendtry_recv- timeouts
select!across multiple channels
Example:
use crossbeam::select;
select! {
recv(rx) -> msg => println!("got {msg:?}"),
default => println!("no message available"),
}This gives you multiplexing without async.
Scoped Threads (The Underrated Feature)
This is the feature most people overlook.
Rust’s std::thread::spawn requires 'static lifetimes.
That forces you to clone or move data into threads.
Crossbeam’s scope lets threads borrow from the stack safely.
use crossbeam::thread;
fn main() {
let data = vec![1, 2, 3];
thread::scope(|s| {
s.spawn(|_| {
println!("first element: {}", data[0]);
});
}).unwrap();
}The compiler guarantees the threads finish before the scope exits.
This eliminates a huge amount of lifetime friction.
In systems code, this is extremely useful.
Where crossbeam Fits
Crossbeam is ideal when:
- You want native threads.
- You need fast channels.
- You care about memory ordering.
- You are building concurrent data structures.
- You don’t want an async runtime.
It’s particularly useful in:
- CPU-bound workloads
- Pipelines
- Parallel algorithms
- Systems utilities
If Tokio is “async orchestration”, Crossbeam is “disciplined threaded concurrency”.
Where It Does Not Fit
Crossbeam does not replace async runtimes.
If you’re doing high-scale network I/O, async usually scales better.
Crossbeam also won’t magically solve design problems.
You still need to think about:
- Ownership
- Contention
- Deadlocks
- Memory visibility
It just gives you better tools.
Trade-offs
Pros
- High-performance channels
- MPMC support
- Scoped threads remove
'staticpain - No runtime required
Cons
- Still manual threading model
- Easier to shoot yourself in the foot than async
- Requires stronger concurrency discipline
Should You Use It?
If you are building CPU-bound concurrent systems or pipelines:
Yes.
If you need structured async I/O:
Probably not — Tokio is a better fit. Crossbeam is not flashy.
It doesn’t come with a runtime banner. It simply provides sharper concurrency primitives, and sometimes that’s exactly what you want.