Writing / Detail

Concurrency: The "Fearless Threads"

2026.04.07
Technology
3130 Words
- Views
- Comments

In modern JavaScript, you use Promises (async/await) or Web Workers for “concurrency.” In Rust, you have OS-level threads (std::thread). These are much more powerful but also more dangerous in other languages.

In Rust, this is called “Fearless Concurrency.” Why “Fearless”? Because the Ownership Contract ensures that it’s impossible for two threads to fight over the same data at the same time. If your code compiles, it’s safe from the most common threading crashes.


🏗️ The 3-Step Narrative

1. Spawning (The “Web Worker”)

Just like a Web Worker runs a separate script, thread::spawn creates a new execution path.

use std::thread;
use std::time::Duration;
fn main() {
let handle = thread::spawn(|| {
for i in 1..10 {
println!("hi number {i} from the spawned thread!");
thread::sleep(Duration::from_millis(1));
}
});
handle.join().unwrap(); // ⏳ This "Waits" for the worker to finish!
}

2. Sharing (The “Arc Mutex” Container)

If multiple threads need to own and change the same data, you need the Arc<Mutex<T>> container.

  • Arc: Atomic Reference Counting (The thread-safe version of Rc).
  • Mutex: Mutual Exclusion (Ensures only one thread can touch the data at a time).
use std::sync::{Arc, Mutex};
let counter = Arc::new(Mutex::new(0));
thread::spawn(move || {
let mut num = counter.lock().unwrap(); // 🔐 Locking for safe access
*num += 1; // Mutate safely!
}); // 🔓 Lock is automatically released here

3. Messaging (The “Channel”)

Instead of sharing memory, Rust programmers often say: “Communicate by sharing, don’t share by communicating.” You send data through a “pipe” (a Channel).

use std::sync::mpsc; // Multiple Producer, Single Consumer
let (tx, rx) = mpsc::channel(); // Transmitter & Receiver
thread::spawn(move || {
tx.send("hi").unwrap(); // 📤 Sending a message
});
let message = rx.recv().unwrap(); // 📥 Blocks until it arrives

NOTE: Parity with JS

This is exactly like worker.postMessage() and window.onmessage.


🔬 From the Official Book

🛡️ The Send & Sync Traits

Every type in Rust decides if it’s safe to share across threads by “signing” these traits:

  • Send: “I can be moved to another thread.”
  • Sync: “I can be accessed from multiple threads at once.”

Most types sign these automatically. If you try to send a non-safe type (like Rc), the compiler will refuse to run your code.


💡 What Concurrency Unlocks

  • Real-Time Parallelism: Use every core on your CPU without worrying about “Data Races.”
  • Reliable Backend Logic: Build high-performance servers that handle millions of requests without the overhead of a garbage collector.
  • Fearless Async: When you move to async/await (using a crate like tokio), you have the same safety guarantees as regular threads.
  • No More Rare Crashes: Threading bugs in C++ are notorious for being “Heisenbugs” (hard to find). In Rust, they are caught before you even run the code.