学习rust_day12
引用循环可能导致内存泄漏
内存泄漏
永远不会被清理掉的内存
- Rust的安全保障使得意外的内存泄漏很难发生,但不是不可能
- 完全防止内存泄漏并不是Rust的保证之一 一> 内存泄漏是内存安全的
- 例如:通过Rc
和RefCell 就可创建出循环引用,导致内存泄漏 - 各个项的引用数永不为0
例:
1 | |
防止引用循环
防止引用循环:将Rc
- 通过Rc:clone创建强引用,增加strong_count。只有当strong_.count为0时,Rc
指向的值才会被清理 - 通过Rc:downgrade创建弱引用,增加weak_count。弱引用不表示所有权,不影响清理时机,因此不会导致循环引用
- Weak
不能直接使用它指向的值,需要通过upgrade方法检查该值是否仍然存在: - 如果Rc
仍存在,upgrade返回Some(Rc ),否则返回None
- 如果Rc
- 应用场景:用树形结构(包含父子关系)替代单向链表
例:
1 | |
多线程 – 无畏并发
- 目标:安全高效的并发编程
- 独特方法:利用所有权和类型系统在编译时防止并发错误
- 优势:在开发阶段而非生产环境中发现错误
- 灵活性:为不同并发模型提供多种工具
使用多线程同时运行代码
- 在大多数当前的操作系统中,被执行程序的代码是在一个进程中运行的,操作系统会同时管理多个进程(Process)。
- 在一个程序内部,你也可以有独立的部分同时运行。运行这些独立部分的功能被称为线程(Thread)。
- 例如,一个网络服务器可以有多个线程,这样它就可以同时响应多个请求。
多线程可导致的问题
- 竞态条件(race condition)
- 即线程以不一致的顺序访问数据或资源
- 死锁(Deadlocks)
- 即两个线程相互等待,导致两个线程都无法继续
- 只在某些情况下发生的错误,难以可靠地重现和修复
例:
1 | |
在线程中使用move闭包
1 | |
消息传递
message passing
- 线程或actors通过发送包含数据的消息来相互通信
- Go语言口号:”不要通过共享内存来通信;而是通过通信来共享内存。”
- Rust的标准库提供了通道(channel)的实现
通道
channel
- 通道是一种程序设计概念,用于在不同线程之间发送数据
- 两个核心部分:发送端(transmitter)和接收端(receiver)
- 当通道的任一端(发送端或接收端)被丢弃时,我们说通道被关闭了
例:
1 | |
共享状态并发
共享数据
- 另一种方法是让多个线程访问相同的共享数据。
- 在某种程度上
- 任何编程语言中的通道都类似于单一所有权
- 共享内存并发就像多重所有权:多个线程可以同时访问相同的内存位置
Mutex互斥锁
- Mutex:Mutual Exclusion
- 互斥锁在任何给定时间只允许一个线程访问某些数据
- 要访问互斥锁中的数据,线程必须请求获取互斥锁的锁
- 锁是互斥锁的一种数据结构,用于跟踪谁当前拥有对数据的独占访问权。
- 互斥锁被描述为通过锁定系统来保护它所持有的数据。
Mutex两条规则
- 在使用数据之前,你必须尝试获取锁
- 当你使用完互斥锁保护的数据后,必须解锁数据,以便其他线程可以获取锁
例:
1 | |
1 | |
Sync & Send traits
- Rust语言本身的并发特性非常少
- 大多数并发功能都是标准库的一部分,而不是语言本身
- 可以编写自己的并发功能或使用第三方库
- 个并发概念:std::marker traits – Sync和Send
Send trait
- Send(marker trait): 所有权可以在线程之间转移
- 几乎所有Rust类型都是Send
- 但有一些例外,例如Rc
不是Send - Rc
仅用于单线程情况 - Rust的类型系统和trait约束确保不会意外地将非Send类型跨线程发送
- 完全由Send类型组成的任何类型也自动标记为Send
- 几乎所有原始类型都是Send原始指针除外
Sync trait
- Sync(marker trait):可以安全地从多个线程|用实现该trait的类型
- 如果&T是Send,则类型T是Sync
- 即该引用可以安全地发送到另一个线程
- 原始类型是Sync
- 完全由Sync类型组成的类型也是Sync
线程安全性与Sync
Sync是Rust中最接近”线程安全”的概念
- “线程安全”指特定数据可以被多个并发线程安全使用
分开Send和Sync特性的原因:一个类型可能是其中之一,两者都是,或两者都不是:
- Rc
:既不是Send也不是Sync - RefCell<-T>:是Send(如果T是Send),但不是Sync
- Mutex
:是Send也是Sync,可用于多线程共享访问 - MutexGuard<‘a,T>:是Sync(如果T是Sync)但不是Send
- Rc
学习rust_day12
https://zlsf-zl.github.io/2026/03/21/学习rust-day12/