rust Send Sync 以及对象安全和对象不安全

开头:菜鸟小明的疑惑

小明:

"李哥,我最近学 Rust,感觉它超级严谨,啥 Send、Sync、对象安全、静态分发、动态分发的,我都搞晕了!为啥 Rust 要设计得这么复杂啊?"

小李(笑):

"别急,Rust 是因为想让代码'安全',又'高性能',所以才有这么多机制。

我们从头讲,慢慢来,一定搞清楚。"


第一章:线程安全是怎么做到的?Send / Sync


Send 是啥?

小明:

"我知道线程是并发执行的,但 Rust 的 Send 是干嘛的?"

小李:

"Send 就是让类型可以在线程之间安全传递,所有权移动。

如果一个类型实现了 Send,说明你可以把它交给另一个线程,不会有问题。"

rust 复制代码
let v = vec![1, 2, 3];

std::thread::spawn(move || {

    println!("{:?}", v); // v 安全移动到线程里

});

小李继续:

"像 Vec、String 这些常见类型,默认都实现了 Send。"


Sync 又是啥?

小明:

"那 Sync 呢?"

小李:

"Sync 是说,多个线程可以安全共享一个类型的 引用 &T。

比如 &i32 是 Sync,多个线程读 &i32 没问题。"

小李举例:

"但如果是 Rc,就不是 Sync,因为它没加锁,线程共享会炸!"

rust 复制代码
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 接口,不管是圆、方块、三角形,统统放一起画!"

rust 复制代码
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。


第三章:动态分发 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,练习对象安全规则!


结尾

小明:

"李哥,真香!终于懂了 Rust 的对象安全和线程安全!"

"原来 Rust 是怕你写出有 bug 的代码,所以宁愿麻烦点,也要你写安全、性能高的代码!"

"学 Rust,心累但放心!

相关推荐
Rust研习社2 天前
组合真的优于继承吗?为什么 Rust 和 Go 都拥抱组合舍弃继承?
后端·rust·编程语言
Aphasia3112 天前
VPN 与内网穿透
安全
红尘散仙3 天前
想写一个像样的终端 App?试试把 React 的开发体验搬进 Rust TUI
前端·rust
vivo互联网技术3 天前
从 Web 到桌面:基于 Tauri 2.0 + Vue 3 打造 vivo 线下门店「大头贴」拍照体验系统
前端·rust
Rust研习社3 天前
这 8 个 Rust 学习资源值得每个新手收藏起来
后端·rust·编程语言
Mr_愚人派3 天前
当"Claude"不再是 Claude:一次第三方 API 代理引发的 AI 身份伪造排查实录
人工智能·安全
LDR0064 天前
Type-C 快充全面升级!LDR6601 赋能个人护理便携电机,重塑剃须刀 / 理发器新体验
c语言·开发语言
雪碧聊技术4 天前
Tree.js是什么?一文讲透
开发语言·javascript·ecmascript
码云数智-园园4 天前
C++20 Modules 模块详解
java·开发语言·spring
swordbob4 天前
NIO的channel中什么是 fd(File Descriptor,文件描述符)
java·开发语言·nio