langShift

并发与异步模型

学习 Rust 的并发编程、异步模型和多线程安全,对比 JavaScript 的事件循环机制

并发与异步模型

📖 学习目标

理解 Rust 的并发编程模型,包括多线程、异步编程和线程安全机制,对比 JavaScript 的单线程事件循环模型。


🎯 执行模型对比

JavaScript 的事件循环

JavaScript 使用单线程事件循环模型:

正在加载...

虽然 JavaScript 本身是单线程的,但可以通过 Web Workers 实现多线程并发,将耗时的计算任务放到后台线程执行,避免阻塞主线程。这类似于 Rust 的多线程,但 Web Workers 之间不能直接共享内存,需要通过消息传递进行通信。

Rust 的多线程模型

Rust 支持真正的多线程并行执行:

正在加载...

执行模型差异

  1. 单线程 vs 多线程: JavaScript 单线程事件循环,Rust 支持多线程并行
  2. 并发 vs 并行: JavaScript 并发非并行,Rust 可以真正并行
  3. 内存安全: JavaScript 运行时检查,Rust 编译时保证线程安全
  4. 性能: JavaScript 受单线程限制,Rust 可以充分利用多核

🔒 线程安全与所有权

共享状态管理

正在加载...

⚡ 异步编程

Rust 的异步编程

正在加载...

异步与多线程对比

正在加载...

🎯 并发模式对比

JavaScript 的并发模式

正在加载...

Rust 的并发模式

正在加载...

🎯 练习题

练习 1: 线程安全计数器

创建一个线程安全的计数器,支持多个线程同时增加计数:

查看答案
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!("最终计数: {}", counter.get_count()); // 应该是 1000
}

练习 2: 异步任务处理

创建一个异步函数,并发处理多个任务并收集结果:

查看答案
use tokio;
use std::time::Duration;
async fn process_task(id: i32) -> String {
tokio::time::sleep(Duration::from_millis(100)).await;
format!("任务 {} 完成", 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!("所有任务完成: {:?}", results);
}

练习 3: 生产者消费者模式

实现一个生产者消费者模式,使用通道进行线程间通信:

查看答案
use std::sync::mpsc;
use std::thread;
use std::time::Duration;
fn producer_consumer() {
let (tx, rx) = mpsc::channel();
// 生产者
let producer = thread::spawn(move || {
for i in 0..10 {
tx.send(format!("产品 {}", i)).unwrap();
thread::sleep(Duration::from_millis(100));
}
});
// 消费者
let consumer = thread::spawn(move || {
for received in rx {
println!("消费: {}", received);
}
});
producer.join().unwrap();
consumer.join().unwrap();
}
fn main() {
producer_consumer();
}

📝 总结

在这一章中,我们学习了 Rust 的并发和异步编程:

  1. 执行模型: Rust 支持真正的多线程并行,JavaScript 是单线程事件循环
  2. 线程安全: Rust 通过所有权系统在编译时保证线程安全
  3. 异步编程: Rust 的 async/await 语法与 JavaScript 类似
  4. 并发模式: 使用 Arc、Mutex、RwLock 等类型安全地共享状态
  5. 性能选择: 多线程适合 CPU 密集型,异步适合 I/O 密集型

关键要点

  • Rust 的所有权系统确保线程安全
  • 异步编程提供高性能的 I/O 处理
  • 选择合适的并发模型很重要
  • 编译时检查避免运行时错误

下一步学习

在下一章中,我们将学习 Rust 的类型系统和特征(Traits),了解如何构建可复用的抽象。


继续学习: 类型系统与特征