langShift

Concurrency & Asynchronous Model

Learn Rust's concurrency, asynchronous model, and multi-threading safety, contrasting with JavaScript's event loop mechanism

Concurrency & Asynchronous Model

📖 Learning Objectives

Understand Rust's concurrency model, including multi-threading, asynchronous programming, and thread safety mechanisms, contrasting with JavaScript's single-threaded event loop model.


🎯 Execution Model Comparison

JavaScript's Event Loop

JavaScript uses a single-threaded event loop model:

正在加载...

Although JavaScript is single-threaded, multi-threaded concurrency can be achieved through Web Workers, which offload time-consuming computation tasks to background threads, preventing the main thread from being blocked. This is similar to Rust's multi-threading, but Web Workers cannot directly share memory and require communication via message passing.

Rust's Multi-threading Model

Rust supports true multi-threaded parallel execution:

正在加载...

Execution Model Differences

  1. Single-threaded vs Multi-threaded: JavaScript single-threaded event loop, Rust supports multi-threaded parallelism
  2. Concurrency vs Parallelism: JavaScript concurrency not parallelism, Rust can truly parallelize
  3. Memory Safety: JavaScript runtime checks, Rust compile-time guarantees thread safety
  4. Performance: JavaScript limited by single-thread, Rust can fully utilize multi-core

🔒 Thread Safety & Ownership

Shared State Management

正在加载...

⚡ Asynchronous Programming

Rust's Asynchronous Programming

正在加载...

Asynchronous vs Multi-threading Comparison

正在加载...

🎯 Concurrency Patterns Comparison

JavaScript's Concurrency Patterns

正在加载...

Rust's Concurrency Patterns

正在加载...

🎯 Exercises

Exercise 1: Thread-Safe Counter

Create a thread-safe counter that supports multiple threads incrementing the count simultaneously:

View Answer
use std::sync::{Arc, Mutex};
use std::thread;
struct Counter {
count: Mutex<i32>,
}
impl Counter {
fn new() -> Self {
Counter {
count: Mutex::new(0),
}
}
fn increment(&self) {
let mut count = self.count.lock().unwrap();
*count += 1;
}
fn get_count(&self) -> i32 {
*self.count.lock().unwrap()
}
}
fn main() {
let counter = Arc::new(Counter::new());
let mut handles = vec![];
for _ in 0..10 {
let counter = Arc::clone(&counter);
let handle = thread::spawn(move || {
for _ in 0..100 {
counter.increment();
}
});
handles.push(handle);
}
for handle in handles {
handle.join().unwrap();
}
println!("Final count: {}", counter.get_count()); // Should be 1000
}

Exercise 2: Asynchronous Task Processing

Create an asynchronous function that concurrently processes multiple tasks and collects the results:

View Answer
use tokio;
use std::time::Duration;
async fn process_task(id: i32) -> String {
tokio::time::sleep(Duration::from_millis(100)).await;
format!("Task {} complete", id)
}
async fn process_all_tasks() -> Vec<String> {
let mut handles = vec![];
for i in 0..10 {
let handle = tokio::spawn(async move {
process_task(i).await
});
handles.push(handle);
}
let mut results = vec![];
for handle in handles {
let result = handle.await.unwrap();
results.push(result);
}
results
}
#[tokio::main]
async fn main() {
let results = process_all_tasks().await;
println!("All tasks complete: {:?}", results);
}

Exercise 3: Producer-Consumer Pattern

Implement a producer-consumer pattern using channels for inter-thread communication:

View Answer
use std::sync::mpsc;
use std::thread;
use std::time::Duration;
fn producer_consumer() {
let (tx, rx) = mpsc::channel();
// Producer
let producer = thread::spawn(move || {
for i in 0..10 {
tx.send(format!("Product {}", i)).unwrap();
thread::sleep(Duration::from_millis(100));
}
});
// Consumer
let consumer = thread::spawn(move || {
for received in rx {
println!("Consumed: {}", received);
}
});
producer.join().unwrap();
consumer.join().unwrap();
}
fn main() {
producer_consumer();
}

📝 Summary

In this chapter, we learned about Rust's concurrency and asynchronous programming:

  1. Execution Model: Rust supports true multi-threaded parallelism, JavaScript is single-threaded event loop
  2. Thread Safety: Rust guarantees thread safety at compile time through the ownership system
  3. Asynchronous Programming: Rust's async/await syntax is similar to JavaScript
  4. Concurrency Patterns: Safely share state using types like Arc, Mutex, RwLock
  5. Performance Choice: Multi-threading for CPU-bound, asynchronous for I/O-bound

Key Takeaways

  • Rust's ownership system ensures thread safety
  • Asynchronous programming provides high-performance I/O handling
  • Choosing the right concurrency model is important
  • Compile-time checks prevent runtime errors

Next Steps

In the next chapter, we will learn about Rust's type system and traits, and how to build reusable abstractions.


Continue Learning: Type System & Traits