返回文章列表

文章

使用Arc + Mutex在多线程中共享并安全地修改一个可变值

部分内容超过 Notion API 单页读取上限,已尽力加载可访问内容。

目录
  1. 如何在多线程中共享并安全地修改一个可变值,也就是对共享可变状态的正确同步。
  2. 🧠 核心知识点
  3. ✅ 正确实现方式
  4. ✅ 示例代码让如下:
  5. ⚠️ 为什么不能只用 Arc?
  6. 🧪 输出示例
  7. 说明所有 10 个线程都成功完成了任务,并安全地更新了共享计数器。

如何在多线程中共享并安全地修改一个可变值,也就是对共享可变状态的正确同步。#

🧠 核心知识点#

概念说明
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

说明所有 10 个线程都成功完成了任务,并安全地更新了共享计数器。#