Rust RefCell 多线程读为什么也panic了?

这是最近实战中遇到的一个小知识点,没理解之前觉得「不可能」,反应过来之后,觉得自己很蠢🤣,借本文记录下。

看一段复现代码:

rust 复制代码
struct MyRefCell<T>(RefCell<T>);

unsafe impl<T> Sync for MyRefCell<T> {}

fn main() {
    let shared = Arc::new(MyRefCell(RefCell::new(0usize)));

    let mut handles = Vec::new();
    for i in 0..100 {
        let s = shared.clone();
        handles.push(thread::spawn(move || {
            thread::sleep(Duration::from_millis(10 * (i % 3) as u64));
            let r = s.0.borrow();
            let r = s.0.borrow_mut();
            println!("thread {} read {}", i, *r);
        }));
    }

    for h in handles {
        let _ = h.join();
    }

    println!("done");
}

​多线程读一个RefCell封装的变量,却发生了panic,原因是:​ ​**already mutably borrowed: BorrowError**

即 RefCell修饰的变量在borrow时检测到已经borrow_mut了,但是代码里其实没有borrow_mut的地方,就很神奇。

另一个迷惑的地方是,多线程读变量居然也是不安全的,也会panic。

或许有小伙伴不理解RefCell,这里简单介绍下:

Rust的借用检查一般在编译期,即一个可变借用(&mut T)同时只能存在一个,不可变借用(&T)和可变借用不能共存;但在实际场景中,借用关系往往很难在编译期满足,这时候就可以用RefCell,RefCell提供两个操作符:borrow()borrow_mut(),支持在​运行时检查借用关系​,如果运行时违法借用规则,会panic。

在我们的代码中,其实​没有违反借用规则​,因为我们只有不可变借用,但还是panic了,为什么呢?

原因在于RefCell borrow() 的​底层实现不是原子的 ​,看着是多线程读,其实内部存在写操作,变成了​隐藏的多线程写​,如下:

可以看出borrow()borrow_mut()内部实现存在写操作,多线程访问时,flag 状态管理可能出错,导致panic。

同样的问题,在Swift中,如果是多线程读一个变量,是安全的吗?

答案我们将在公众号「非专业程序员Ping」的下一期文章揭晓,欢迎订阅交流!

相关推荐
初级代码游戏16 小时前
iOS开发 SwiftUI 14:ScrollView 滚动视图
ios·swiftui·swift
初级代码游戏18 小时前
iOS开发 SwitftUI 13:提示、弹窗、上下文菜单
ios·swiftui·swift·弹窗·消息框
zhyongrui21 小时前
托盘删除手势与引导体验修复:滚动冲突、画布消失动画、气泡边框
ios·性能优化·swiftui·swift
zhangfeng11331 天前
CSDN星图 支持大模型微调 trl axolotl Unsloth 趋动云 LLaMA-Factory Unsloth ms-swift 模型训练
服务器·人工智能·swift
superman超哥2 天前
Serde 性能优化的终极武器
开发语言·rust·编程语言·rust serde·serde性能优化·rust开发工具
sayang_shao2 天前
Rust多线程编程学习笔记
笔记·学习·rust
zhyongrui2 天前
SnipTrip 发热优化实战:从 60Hz 到 30Hz 的性能之旅
ios·swiftui·swift
鸿乃江边鸟2 天前
Spark Datafusion Comet 向量化Rust Native--读数据
rust·spark·native·arrow
硬汉嵌入式2 天前
基于Rust构建的单片机Ariel RTOS,支持Cortex-M、RISC-V 和 Xtensa
单片机·rust·risc-v
大熊猫侯佩3 天前
Neo-Cupertino 档案:撕开 Actor 的伪装,回归 Non-Sendable 的暴力美学
swift·observable·actor·concurrency·sendable·nonsendable·data race