Rust 并发共享数据选型总结:Mutex vs ArcSwap
Rust 并发共享数据选型总结:Mutex vs ArcSwap
本文档清晰对比 Rust 开发中读多写少、共享可变数据场景下最常用的两种方案:Arc<Mutex<T>> 和 Arc<ArcSwap<T>>,并补充常用拓展方案,用于快速选型、记忆和团队参考。
一、核心对比(速查版)
| 特性 | Arc<Mutex<Vec<T>>> | Arc<ArcSwap<Vec<T>>> |
|---|---|---|
| 核心原理 | 互斥排他锁,同一时间只允许一个线程访问 | 无锁原子指针替换,读写分离 |
| 并发读 | 阻塞,多线程读必须排队 | 无锁,海量线程同时读无性能损耗 |
| 并发写 | 阻塞所有读写操作 | 不阻塞读,仅原子替换指针 |
| 数据修改 | 原地修改 | 写时复制(COW),生成新数据替换 |
| 性能表现 | 低并发可用,高并发锁竞争严重 | 读性能极高,高并发首选 |
| 一致性 | 强一致性,修改立即生效 | 最终一致性,读拿到当前快照 |
| 使用难度 | 简单,lock 即可读写 | 稍复杂,写需要克隆 + 替换 |
| 适用场景 | 读写频繁、需要强一致性 | 读多写少(规则 / 配置 / 白名单) |
二、详细定义与用法
1. Arc<Mutex<T>>
-
依赖:Rust 标准库,无需额外引入
-
作用:多线程安全共享可变数据,通过互斥锁保证同一时间只有一个线程操作数据
-
结构含义:
-
Arc:原子引用计数,支持跨线程共享所有权 -
Mutex:互斥锁,提供独占访问能力
-
基础用法
use std::sync::{Arc, Mutex};
// 初始化
let shared_data = Arc::new(Mutex::new(vec![1, 2, 3]));
// 读/写:必须加锁,阻塞等待
let mut data = shared_data.lock().unwrap();
data.push(4); // 原地修改
2. Arc<ArcSwap<T>>
-
依赖:第三方库
arc-swap -
作用:高并发读、极少写场景的最优解,无锁读、原子写
-
结构含义:
-
ArcSwap:无锁数据结构,原子替换Arc指针 -
读操作无锁,写操作不影响正在进行的读
-
基础用法
use arc_swap::{ArcSwap, Arc};
use std::sync::Arc as StdArc;
// 初始化
let shared_data = ArcSwap::from(StdArc::new(vec![1, 2, 3]));
// 读:无锁,瞬间完成
let current = shared_data.load();
// 写:创建新数据,原子替换
let new_data = StdArc::new(vec![1, 2, 3, 4]);
shared_data.store(new_data);
三、记忆口诀(永久不忘)
-
Mutex** = 公共厕所** 读写都要排队,一次只能一个人用,阻塞、独占、低并发 -
ArcSwap** = 公告栏** 多人同时看(读无锁),管理员直接换新海报(写替换),不影响读者
四、业务选型指南
✅ 推荐使用 Arc<Mutex<T>>
-
数据读写都很频繁
-
需要强一致性,修改必须立即生效
-
逻辑简单,不想处理写时复制
-
并发量低,无性能压力
✅ 推荐使用 Arc<ArcSwap<T>>
-
读多写少(99% 业务场景)
-
配置、规则、路由表、白名单、静态数据
-
高并发、低延迟要求
-
允许最终一致性(读取快照)
五、常用拓展方案(补充)
除了上述两种,Rust 并发共享数据还有以下高频方案,可根据场景扩展使用:
1. Arc<RwLock<T>> 读写锁
-
特点:读共享、写独占
-
对比:
-
比
Mutex并发读更强 -
比
ArcSwap写更方便(原地修改)
-
-
适用:读多写少,希望写操作简单、强一致性
-
缺点:高并发读性能不如
ArcSwap
2. OnceCell / LazyCell
-
特点:一次性初始化,只读不写
-
适用:全局配置、单例、启动加载后永不修改的数据
-
优点:无锁、零开销、最简单安全
3. tokio::sync::Mutex
-
特点:异步互斥锁,用于
async代码 -
适用:异步任务中共享可变数据
-
注意:不能在同步代码中使用,不要与标准库
Mutex混用
六、最终总结
-
标准库、简单场景、读写均衡 → 用
Arc<Mutex<T>> -
高并发读、规则 / 配置、读多写少 → 用
Arc<ArcSwap<T>> -
读多写少、希望写方便 → 用
Arc<RwLock<T>> -
初始化后永不修改 → 用
OnceCell/LazyCell -
异步环境 → 用
tokio::sync::Mutex
本文由萧兮的博客原创发布,欢迎转载,转载务必保留原文链接。
萧兮的博客:https://www.20010515.xyz · 原文:https://www.20010515.xyz/posts/019e8cc4-27b0-7670-b3b4-645bcfef0d32