Rust RefCell 多线程读为什么也 panic 了?
这是最近实战中遇到的一个小知识点,没理解之前觉得「不可能」,反应过来之后,觉得自己很蠢🤣,借本文记录下。
看一段复现代码:
多线程读一个 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」的下一期文章揭晓,欢迎订阅交流!
版权声明: 本文为 InfoQ 作者【非专业程序员Ping】的原创文章。
原文链接:【http://xie.infoq.cn/article/c6a41e7fb715fbc23864b2c25】。文章转载请联系作者。







评论