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),了解如何建構可複用的抽象。


繼續學習: 型別系統與特徵