读完本篇你能学到什么
- Rust 原子操作的底层实现差异:理解 x86-64 与 ARM64
架构如何实现原子操作(如 x86 的
lock
前缀指令与 ARM 的load-exclusive/store-exclusive
机制),以及这些差异对并发性能的影响。 - 处理器缓存与并发性能的关联:掌握缓存行(Cache
Line)的工作原理,学会通过内存对齐(如
#[repr(align(64))]
)避免伪共享(False Sharing),减少多线程竞争时的缓存失效开销。 - 指令重排序与内存模型的底层逻辑:理解处理器和编译器为何重排指令,以及
Release/Acquire
内存顺序如何通过硬件屏障(如 x86 的mfence
、ARM 的dmb
)建立跨线程的可见性保证。 - 跨平台并发编程的优化策略:针对 x86 强有序和 ARM
弱有序架构的特点,掌握自旋锁、原子操作的平台适配技巧(如 ARM
上优先使用
compare_exchange_weak
减少重试)。 - 用工具验证底层实现的方法:学会通过 Compiler Explorer 或本地汇编查看工具,验证 Rust 原子操作对应的处理器指令,建立 “高级语言 - 汇编 - 硬件” 的映射认知。
- 并发代码的性能瓶颈定位:识别缓存一致性协议(如 MESI)对多线程操作的影响,能够通过实验(如基准测试)量化不同架构下的性能差异。
- Rust 标准库并发原语的底层原理:从处理器指令角度理解
Mutex
、Arc
等类型如何利用原子操作和内存屏障保证线程安全,而非仅停留在 API 使用层面。
指令集
两种指令集:
- CISC(Complex Instruction Set Computing,复杂指令集)
- RISC(Reduced Instruction Set Computing,精简指令集)
二者对比:
特征 | RISC | CISC |
---|---|---|
指令集 | 精简,指令数目少 | 复杂,指令数目多 |
指令复杂性 | 指令简单,每条指令执行单一功能 | 指令复杂,可以执行多个功能 |
寻址方式 | 简单寻址方式 | 复杂寻址方式 |
硬件实现 | 易于实现 | 实现复杂 |
编译器 | 高效编译器 | 编译器效率相对较低 |
运算速度 | 快速 | 相对慢 |
具体可参考:risc vs. cisc。
两种指令集分别对应两种最典型的计算机架构:
- x86-64:基于 CISC(复杂指令集)的 64 位扩展架构,由 AMD 设计并主导,兼容 x86 32 位生态,通过硬件复杂性换取高性能与广泛兼容性,主导桌面与服务器领域。
- arm64:基于 RISC(精简指令集)的 64 位架构,由 ARM 设计,以精简指令、高能效为核心,原生支持低功耗场景,主导移动设备并逐步扩展至服务器与 PC 领域。
在本篇中,我们只涉及 2 个平台:
- aarch64-unknown-linux-musl
- x86_64-unknown-linux-musl
要将 Rust 代码编译为指定平台的可执行文件:
安装对应的目标平台
1
2rustup target add x86_64-unknown-linux-musl # x86_64
rustup target add aarch64-unknown-linux-musl # ARM64编译时使用
--target
标志1
2cargo build --release --target x86_64-unknown-linux-musl
cargo build --release --target aarch64-unknown-linux-musl
查看 Rust 汇编代码
- cargo rustc --release -- --emit asm
查看各种原子操作对应的汇编语言,与其非原子类操作进行比较
- Load/Store
- Read-Modify-Write
- fetch_add
- fetch_or
- compare_exchange
- compare_exchange_weak
处理器缓存机制
重排序
- store buffers
- invalidation queues
- pipelining
内存顺序
- x86-64 强制顺序
- arm64 弱顺序
- 实验
- 内存屏障
总结