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

【Rust】17-Send、Sync 与并发安全抽象

Send、Sync 与并发安全抽象

研究目标

  • 理解SendSync如何表达跨线程安全。
  • 区分所有权转移、共享引用和内部可变性。
  • 掌握 Rust 并发抽象背后的类型约束。

Rust 并发安全的基础

Rust 的并发安全不是来自某个单独的锁库,而是所有权、借用和类型系统共同作用的结果。核心原则是:

  • 数据可以被移动到另一个线程,但必须安全。
  • 数据可以被多个线程共享引用,但共享访问必须安全。
  • 可变共享需要同步原语或原子操作。

SendSync是两个标记 trait,用于表达这些性质。

Send

Send表示一个类型的值可以安全地转移到另一个线程。

usestd::thread;fnmain(){lettext=String::from("hello");lethandle=thread::spawn(move||{println!("{text}");});handle.join().unwrap();}

StringSend,所以可以通过move闭包转移到新线程。

反例是Rc<T>

usestd::rc::Rc;usestd::thread;fnmain(){letvalue=Rc::new(1);// thread::spawn(move || {// println!("{value}");// });}

Rc<T>的引用计数更新不是线程安全的,所以它不是Send

Sync

Sync表示一个类型可以安全地被多个线程通过共享引用访问。形式化地说,如果&TSend,那么TSync

i32StringVec<T>在合适条件下都是Sync,因为多个线程共享不可变引用读取它们是安全的。

RefCell<T>不是Sync

usestd::cell::RefCell;fnmain(){letvalue=RefCell::new(1);*value.borrow_mut()+=1;}

RefCell<T>的借用计数是非线程安全的运行时检查,不能被多个线程同时访问。

Arc 与 Mutex

跨线程共享所有权通常使用Arc<T>

usestd::sync::Arc;usestd::thread;fnmain(){letvalue=Arc::new(String::from("shared"));letcloned=Arc::clone(&value);lethandle=thread::spawn(move||{println!("{cloned}");});println!("{value}");handle.join().unwrap();}

如果需要跨线程修改共享数据,使用Mutex<T>

usestd::sync::{Arc,Mutex};usestd::thread;fnmain(){letcounter=Arc::new(Mutex::new(0));letmuthandles=Vec::new();for_in0..4{letcounter=Arc::clone(&counter);handles.push(thread::spawn(move||{letmutguard=counter.lock().unwrap();*guard+=1;}));}forhandleinhandles{handle.join().unwrap();}println!("{}",*counter.lock().unwrap());}

Arc<Mutex<T>>的含义是:多个线程共享同一个所有权句柄,每次修改前先获得互斥锁。

RwLock 与读多写少

RwLock<T>允许多个读者或一个写者:

usestd::sync::RwLock;fnmain(){letvalue=RwLock::new(vec![1,2,3]);{letread=value.read().unwrap();println!("{}",read.len());}{letmutwrite=value.write().unwrap();write.push(4);}}

读多写少场景中,RwLock可能比Mutex更合适。但具体性能取决于锁实现、竞争程度和临界区大小。

原子类型

简单计数器可以使用原子类型:

usestd::sync::atomic::{AtomicUsize,Ordering};usestd::sync::Arc;usestd::thread;fnmain(){letcounter=Arc::new(AtomicUsize::new(0));letmuthandles=Vec::new();for_in0..4{letcounter=Arc::clone(&counter);handles.push(thread::spawn(move||{counter.fetch_add(1,Ordering::Relaxed);}));}forhandleinhandles{handle.join().unwrap();}println!("{}",counter.load(Ordering::Relaxed));}

原子操作避免锁,但内存序选择很重要。Relaxed只保证原子性,不建立跨线程同步顺序。复杂并发算法应谨慎使用原子并配合测试和模型检查。

Channel

另一种并发思路是消息传递:

usestd::sync::mpsc;usestd::thread;fnmain(){let(tx,rx)=mpsc::channel();thread::spawn(move||{tx.send(String::from("hello")).unwrap();});letmessage=rx.recv().unwrap();println!("{message}");}

channel 通过移动消息所有权减少共享状态。很多系统可以优先用消息传递表达工作流,只在必要时共享可变状态。

自动实现与 unsafe impl

SendSync通常由编译器自动推导。如果类型的所有字段都是Send,该类型一般也是SendSync也类似。

手写unsafe impl Sendunsafe impl Sync意味着你向编译器承诺这个类型满足跨线程安全不变量:

structMyPointer(*mutu8);// unsafe impl Send for MyPointer {}

这非常危险。除非你完全理解内部别名、生命周期、同步和释放规则,否则不要手写这些实现。

async 中的 Send

异步任务也常遇到Send

tokio::spawn(asyncmove{// future 必须 Send + 'static});

如果 future 跨.await保存了非 Send 值,整个 future 就不是 Send。解决方式包括改用Arc、缩小非 Send 值作用域、使用本地任务执行器。

常见误解

  • Arc<T>只提供线程安全引用计数,不让T自动可变。
  • Mutex<T>保护的是数据访问,不是让逻辑自动无死锁。
  • Send是所有权跨线程转移,Sync是共享引用跨线程访问。
  • RefCell<T>是单线程内部可变性,不是线程同步工具。

继续研究

  • Rustonomicon:Send and Sync。
  • Rust Book:fearless concurrency。
  • Rust Reference:marker traits、undefined behavior、data races。
  • Loom:并发模型测试工具。

后记

2026年6月11日15点23分于上海。

http://www.rkmt.cn/news/1509394.html

相关文章:

  • 2024广州民办高中测评:零基础择校避坑指南 - 服务品牌热点
  • 2026年好用的视频去水印软件有哪些?视频去水印软件推荐实用教程
  • F28335的I2C时钟配置踩坑实录:从400kHz降到100kHz才稳定的背后
  • AI写论文绝佳选择,4款AI论文写作工具,轻松打造高质量论文!
  • 2026深圳黄金回收便民服务指南,规范门店名录与特色优势全览! - 奢侈品交易观察员
  • 2026年长春小提琴培训行业观察:教学体系、师资结构与学员成长路径分析 - 优质品牌商家
  • 从汽车级EEPROM选型到开源磨损均衡算法:手把手教你设计高可靠嵌入式存储模块(附避坑指南)
  • 别再死记硬背了!用Python 3.10手把手模拟TDM时分复用,5分钟搞懂同步与异步
  • 从玩具车到真汽车:聊聊EEPROM磨损均衡算法在Arduino和STM32上的开源实现
  • 如何用ImageSearch在5分钟内实现本地图像搜索:千万级图片库管理终极指南
  • Rust + GPU加速?拆解Zed编辑器‘快’背后的技术栈与未来潜力
  • Autosar DSL模块实战:如何用Vector Configurator Pro精准控制诊断时序与Pending响应?
  • Python 高手编程系列三千四百四十二:创建一个包
  • JetBrains IDE试用延期解决方案:ide-eval-resetter完整指南
  • 扩散模型在视频生成中的手部与相机控制技术
  • 别再只看CPU核数了!手把手教你用FLOPS公式,自己算算你的电脑和显卡到底有多强
  • 别再只会用方括号了!MATLAB矩阵拼接的四种写法(含horzcat/vertcat/cat函数对比)
  • Mythos解析:Claude推理增强机制与结构化验证实践
  • 2026年常州遗产继承纠纷律师推荐 陈志豪律师15年专业专注 - 本地品牌推荐
  • 从libcams.dll到NXOpen:一份给NX/UG二次开发者的刀路编辑函数迁移与版本兼容指南(含NX12前后对比)
  • AR贺卡实战指南:轻量化Web AR+印刷双轨设计
  • 如何在3分钟内实现智慧树自动刷课:前端自动化技术深度实践
  • 高斯过程与神经网络融合加速蛋白质结构预测
  • 2026年6月在线SS分析仪主要品牌排行榜 - 仪表品牌排行榜
  • Seraphine智能助手:从青铜到王者的英雄联盟游戏体验革命
  • Sqribble:基于模板的文档操作系统深度解析
  • Nectin-4抗体如何成为实体瘤靶向治疗新星?
  • NLP特征工程四基石:POS、句法分析、NER与语义N-gram
  • 信奥赛C++提高组csp-s之单调栈(案例实践2)
  • NLP辅助系统性文献综述数据提取:精准、可审计、可复现