文章
使用Arc + Mutex在多线程中共享并安全地修改一个可变值
部分内容超过 Notion API 单页读取上限,已尽力加载可访问内容。
目录
如何在多线程中共享并安全地修改一个可变值,也就是对共享可变状态的正确同步。#
🧠 核心知识点#
| 概念 | 说明 |
|---|---|
Arc<T> | 原子引用计数智能指针,用于在多线程中共享数据 |
Mutex<T> | 互斥锁,保护某个值,使得在任何时刻只有一个线程可以访问它 |
Arc<Mutex<T>> | 最常见的多线程共享可变数据模式 |
✅ 正确实现方式#
你必须将 JobStatus 包裹在 Mutex 中,并通过 lock() 方法获取可变引用。
✅ 示例代码让如下:#
use std::{sync::{Arc, Mutex}, thread, time::Duration};
struct JobStatus {
jobs_done: u32,
}
fn main() {
// ✅ Arc + Mutex 实现线程安全共享可变状态
let status = Arc::new(Mutex::new(JobStatus { jobs_done: 0 }));
let mut handles = Vec::new();
for _ in 0..10 {
let status_shared = Arc::clone(&status);
let handle = thread::spawn(move || {
thread::sleep(Duration::from_millis(250));
// ✅ 加锁并修改共享数据
let mut status = status_shared.lock().unwrap();
status.jobs_done += 1;
});
handles.push(handle);
}
for handle in handles {
handle.join().unwrap();
}
// ✅ 主线程读取锁内值
println!("Jobs done: {}", status.lock().unwrap().jobs_done);
}
⚠️ 为什么不能只用 Arc?#
Arc本身 只能共享不可变引用。- 如果你尝试
.jobs_done += 1,Rust 会报错,因为多个线程同时修改数据是未定义行为。 Mutex提供了一个锁来确保一次只有一个线程可以访问数据。
🧪 输出示例#
你将看到输出:
Jobs done: 10