开头:菜鸟小明的疑惑
小明:
“李哥,我最近学 Rust,感觉它超级严谨,啥 Send、Sync、对象安全、静态分发、动态分发的,我都搞晕了!为啥 Rust 要设计得这么复杂啊?”
小李(笑):
“别急,Rust 是因为想让代码‘安全’,又‘高性能’,所以才有这么多机制。
我们从头讲,慢慢来,一定搞清楚。”
---
第一章:线程安全是怎么做到的?Send / Sync
---
Send 是啥?
小明:
“我知道线程是并发执行的,但 Rust 的 Send 是干嘛的?”
小李:
“Send 就是让类型可以在线程之间安全传递,所有权移动。
如果一个类型实现了 Send,说明你可以把它交给另一个线程,不会有问题。”
let v = vec![1, 2, 3];
std::thread::spawn(move || {
println!("{:?}", v); // v 安全移动到线程里
});
小李继续:
“像 Vec<T>、String 这些常见类型,默认都实现了 Send。”
---
Sync 又是啥?
小明:
“那 Sync 呢?”
小李:
“Sync 是说,多个线程可以安全共享一个类型的 引用 &T。
比如 &i32 是 Sync,多个线程读 &i32 没问题。”
小李举例:
“但如果是 Rc<T>,就不是 Sync,因为它没加锁,线程共享会炸!”
use std::rc::Rc;
let rc = Rc::new(5);
std::thread::spawn(move || {
println!("{}", rc); // 编译报错!Rc 不是 Send
});
---
Rust 怎么防止线程不安全?
小明:
“那怎么防止?我不小心就传了个 Rc 进去怎么办?”
小李(笑):
“防不住啊?放心!Rust 的编译器帮你守着!
你跨线程传东西,Rust 会自动检查类型有没有 Send 和 Sync,
不符合就不给你编译过!
连运行都跑不起来,根本不可能线程不安全。”
---
第二章:对象安全是干嘛的?
---
什么是对象安全?
小明:
“线程安全我懂了。那对象安全呢?”
小李:
“对象安全是另一回事,管的是多态和动态分发。”
“Rust 里,想通过 dyn Trait 传递 trait 对象,trait 必须是对象安全的。
否则 Rust 编译器不让用。”
---
对象安全有啥用?
小李:
“对象安全让我们可以搞‘接口多态’,
比如你想写一个 draw 接口,不管是圆、方块、三角形,统统放一起画!”
trait Drawable {
fn draw(&self);
}
fn render(shape: &dyn Drawable) {
shape.draw();
}
“你能写 &dyn Drawable,是因为 Drawable 满足对象安全。”
---
什么叫不对象安全?
小明:
“那为啥有些 trait 不对象安全?”
小李:
“比如有个方法返回 Self,
dyn Trait 根本不知道 Self 是谁,咋办?
编译器说:‘我拒绝!’”
trait Factory {
fn create() -> Self; // 返回 Self,不对象安全
}
---
对象安全的规则
小李总结:
1. 方法不能返回 Self(除非在 Box、Arc 里包起来)。
2. 不能有泛型方法。
3. 接口方法的 self 必须是 &self、&mut self 或 Box<Self>。
---
第三章:动态分发 VS 静态分发
---
动态分发(对象安全)
小李:
“dyn Trait 背后有个 vtable 指针,
运行时根据类型调用不同的方法。
这种叫动态分发,更灵活,但有运行时开销。”
---
静态分发(泛型、高性能)
小李继续:
“泛型和不对象安全的 trait,
Rust 编译器会为每个类型单独生成代码,
这种叫静态分发,零开销、性能好。”
---
第四章:Rust 为什么这么设计?
---
小明:
“李哥,我觉得 Rust 好麻烦,为什么要搞这么复杂?”
小李(认真):
“为了安全和性能!
C/C++ 时代:线程不安全、指针乱飞、内存泄露。
Rust 时代:编译时发现所有问题,安全有保障。
还能零开销,静态分发快得飞。”
---
第五章:总结表格
---
第六章:练习时间!
小李:
“明白了?来,练习一下!”
写个 trait Shape,加 fn area(&self) -> f64;,实现 dyn Shape 多态!
写个 trait Cloneable,fn clone_box(&self) -> Box<dyn Cloneable>,练习对象安全规则!
---
结尾
小明:
“李哥,真香!终于懂了 Rust 的对象安全和线程安全!”
“原来 Rust 是怕你写出有 bug 的代码,所以宁愿麻烦点,也要你写安全、性能高的代码!”
“学 Rust,心累但放心!