当前位置: 首页 > news >正文

Arc + Mutex / RwLock / Atomic 才是 Rust 并发全貌!

Rust 里的并发模型看起来复杂,但真正的核心其实很收敛:Arc 只是把“谁拥有数据”这件事从单线程语义扩展到了多线程语义,而真正决定系统行为的,是 Arc 外层包裹的结构。很多人一开始会把 Arc 当成并发工具,但在工程里它更像是一个边界层,把“共享”这件事从所有权系统中单独剥离出来。

在单线程模型里,Rust 强制一个值只能有一个所有者,这让内存管理非常清晰,但一旦进入多线程或异步任务,这个假设就不成立了,因为同一份数据需要被多个执行单元同时访问。Arc 在这里的作用不是改变这条规则,而是让多个执行单元都能“合法地持有同一个入口”,它通过引用计数把生命周期问题转移到运行时管理,但数据本身仍然保持 Rust 默认的不可变约束。

usestd::sync::Arc;fnmain(){letdata=Arc::new(vec![1,2,3]);leta=Arc::clone(&data);letb=Arc::clone(&data);println!("{:?}",a);println!("{:?}",b);}

这段代码里看不到任何并发行为,但它揭示了 Arc 的第一层本质:多个变量只是共享同一块数据的“入口”,而不是复制数据本身。也正因为如此,Arc 单独使用时,整个结构是只读的。

当系统进入真正的并发场景时,问题就从“能不能共享”变成“共享之后能不能修改”。Arc 在这里不提供答案,它只是提供入口,所以必须引入额外结构来承担并发控制。

在同步线程模型里,最常见的组合是 Arc 和 Mutex。Mutex 的作用不是优化性能,而是把并发访问重新压回到一个串行区间,让同一时刻只有一个线程可以进入临界区。Arc 仍然只是负责把同一份 Mutex 分发到多个线程中。

usestd::sync::{Arc,Mutex};usestd::thread;fnmain(){letcounter=Arc::new(Mutex::new(0));letmuthandles=vec![];for_in0..10{letc=Arc::clone(&counter);handles.push(thread::spawn(move||{letmutv=c.lock().unwrap();*v+=1;}));}forhinhandles{h.join().unwrap();}println!("{}",*counter.lock().unwrap());}

这段结构的关键点不在“用了 Mutex”,而在于整个并发模型被重新定义为“共享入口 + 串行修改”。Arc 只是让多个线程进入同一个状态容器,而 Mutex 决定这些访问如何被排列。

当系统的访问模式发生变化,比如读操作远多于写操作,Mutex 的串行模型就会开始显得笨重,因为即使是读取也会参与竞争。RwLock 在这里的意义不是“更高级”,而是把访问路径拆成了两个层次:读可以并行存在,而写仍然保持独占。这种结构在配置、路由表或者规则系统里很常见,因为这些数据的写入频率天然较低。

usestd::sync::{Arc,RwLock};usestd::thread;fnmain(){letconfig=Arc::new(RwLock::new(String::from("v1")));letmuthandles=vec![];foriin0..5{letc=Arc::clone(&config);handles.push(thread::spawn(move||{ifi%2==0{letmutw=c.write().unwrap();*w=format!("v{}",i);}else{letr=c.read().unwrap();println!("{}",*r);}}));}forhinhandles{h.join().unwrap();}}

如果把视角再往下压一层,会发现锁其实并不是唯一解。当数据结构足够简单,比如只是一个计数器或者状态标志,引入 Mutex 反而增加了不必要的调度开销。Atomic 在这里提供的是另一种路径,它直接利用 CPU 层面的原子指令完成读写操作,从模型上绕过了锁。

usestd::sync::{Arc,atomic::{AtomicUsize,Ordering}};usestd::thread;fnmain(){letcounter=Arc::new(AtomicUsize::new(0));letmuthandles=vec![];for_in0..10{letc=Arc::clone(&counter);handles.push(thread::spawn(move||{c.fetch_add(1,Ordering::SeqCst);}));}forhinhandles{h.join().unwrap();}println!("{}",counter.load(Ordering::SeqCst));}

当进入异步运行时(例如 Tokio)之后,Arc 的角色没有发生变化,它依然只是共享入口层,但同步锁的行为必须调整,因为异步运行时依赖任务调度而不是线程阻塞。如果在 async 环境中使用 std::sync::Mutex,会导致线程被卡住,从而破坏整个 runtime 的调度效率。

usestd::sync::Arc;usetokio::sync::Mutex;#[tokio::main]asyncfnmain(){letstate=Arc::new(Mutex::new(0));letmuthandles=vec![];for_in0..10{lets=Arc::clone(&state);handles.push(tokio::spawn(asyncmove{letmutv=s.lock().await;*v+=1;}));}forhinhandles{h.await.unwrap();}println!("{}",*state.lock().await);}

异步 Mutex 的关键变化不在语法,而在执行语义上:锁的等待不再占用线程,而是让出任务执行权,这使得并发从“线程竞争”转变成“任务调度”。

同样的结构在 RwLock 上也成立,只是读写路径被进一步拆分,使得高并发读取不会阻塞彼此。

usestd::sync::Arc;usetokio::sync::RwLock;#[tokio::main]asyncfnmain(){letdata=Arc::new(RwLock::new(String::from("v1")));letd1=Arc::clone(&data);letreader=tokio::spawn(asyncmove{letr=d1.read().await;println!("{}",r);});letd2=Arc::clone(&data);letwriter=tokio::spawn(asyncmove{letmutw=d2.write().await;*w=String::from("v2");});reader.await.unwrap();writer.await.unwrap();}

如果把整个结构收敛起来看,Arc 始终只做一件事:把数据的所有权扩展到多个执行单元,而所有并发语义的变化都发生在它的外层结构中。Mutex 让访问变成串行,RwLock 把读写路径拆开,Atomic 则直接绕过锁体系,而在异步环境中,这一切只是从“阻塞线程”变成“挂起任务”。

理解这一点之后,Arc 就不再是一个需要记忆组合的类型,而是并发模型中的一个稳定不变的入口层,变化的永远是它外面的那一圈结构。

http://www.jsqmd.com/news/1093907/

相关文章:

  • 阿里最新“SpringCloud微服务”全解手册:程序员进阶必备!
  • 深度把玩二手欧米茄星座的老哥,建议先放大50倍看看这处机芯公差
  • 如何用 Claude API 总结客服工单,并找出高频问题
  • Python的__mro__方法解析顺序与super函数在多继承中的查找路径
  • 企业微信会话存档与SCRM实战:全链路客服数据统计
  • 前端音视频处理入门
  • 先说结论:C++/WinRT 不一定要专用模板
  • 在线音视频处理工具,不上传文件的在线视频压缩工具!
  • 已经能自动发抖音了
  • 收不到WhatsApp验证码?别急着砸手机,这5个坑你肯定踩过
  • Python Web 项目使用 PyInstaller 打包为 Windows EXE 的常见问题与解决方法
  • Keil MDK 编译输出内存分段详解
  • 收藏!小白程序员必看:手把手教你搭建可评测的RAG大模型系统
  • ManageEngine卓豪-企业为什么需要AD域审计工具?
  • AI FDE培训:让AI从能演示,到能干活
  • 高活性浓缩洗衣液怎么选?两款家用高性价比品牌实测
  • 千匠智元AI斩获第八届创新发展论坛金i奖,领跑产业AI创新
  • 新160个CrackMe039-eKH.1、040-DaNiEl-RJ.1、041-genocide1逆向分析
  • AI 赋能训练推理平台 Java + SpringBoot MySQL Maven EasyAI FFmpeg支持人脸识别、门禁、人员入出检测、人员跌倒检测等功能 基于深度学习模型,可自定义训练数据
  • VSCode插件变黑客后门!GitHub 3800个仓库被攻破
  • 湖北工业大学《线性代数》期末试卷及答案2016-2024学年PDF
  • 【从0到1构建一个ClaudeAgent】协作-团队协议
  • 2026年智泊第23期AGI大模型应用开发实践班v6.0,智泊-最新AGI大模型全栈课12期|2025年9月
  • 提示词三要素:角色锚定、任务边界与输出契约
  • 文科生怎么转型科创赛道-硕士进修选择与交大MTT培养路径详解
  • 基于Appium与Python的拼多多百亿补贴商品价格自动化监控方案
  • 老板周五17:30丢了个网页让我“照着做一版“,这次我只用了3分钟
  • 2026 电子轴凹版印刷机方案制作逻辑,专业生产厂家国伟机械定制服务解读
  • 万维盈创 CCEP 持证扬尘(噪声)在线监测仪|建筑工地、道路扬尘、工业无组织排放合规监测优选设备
  • 企业微信双动作更新:5.0.9新版+企微AI大圆来了