Day 5:共享狀態與 Mutex
學習目標
- 用 Mutex 保護共享資料
- 用 Arc 讓多執行緒共享所有權
- 避免死鎖與資料競爭
今日重點
Mutex:互斥鎖
use std::sync::Mutex;
fn main() {
let m = Mutex::new(5);
{
let mut num = m.lock().unwrap(); // 取得鎖
*num = 6; // 修改受保護資料
} // 離開 scope 自動釋放鎖
println!("m = {:?}", m); // Mutex { data: 6 }
}
lock() 回傳 MutexGuard,Drop 時自動解鎖。透過 * 解引用修改裡面的值。
Arc:原子引用計數
Rc 不能跨執行緒(非 Send)。跨執行緒共享所有權要用 Arc(Atomic Rc)。
use std::sync::{Arc, Mutex};
use std::thread;
fn main() {
let counter = Arc::new(Mutex::new(0));
let mut handles = vec![];
for _ in 0..10 {
let counter = Arc::clone(&counter); // 增加計數
let handle = thread::spawn(move || {
let mut num = counter.lock().unwrap();
*num += 1;
});
handles.push(handle);
}
for handle in handles {
handle.join().unwrap();
}
println!("Result: {}", *counter.lock().unwrap()); // 10
}
練習
use std::sync::{Arc, Mutex};
use std::thread;
fn main() {
// 讓 4 個執行緒各把總和加 1000
let total = Arc::new(Mutex::new(0));
let mut handles = vec![];
for _ in 0..4 {
let total = Arc::clone(&total);
handles.push(thread::spawn(move || {
for _ in 0..1000 {
*total.lock().unwrap() += 1;
}
}));
}
for h in handles { h.join().unwrap(); }
println!("total = {}", *total.lock().unwrap()); // 4000
}
自我檢查
深入連結
- The Book 第 16 章「Shared-State Concurrency」