rust - 为什么我不能将借来的值放在 Mutex 后面并将其传递给另一个线程?
问题描述
我试图将借来的值放在 a 后面,Mutex
但借用检查器遇到问题。这是一个简化的代码,演示了我遇到的问题:
use std::{
marker::PhantomData,
sync::{Arc, Mutex},
};
struct Test<'a> {
d: PhantomData<Mutex<&'a u8>>,
}
impl<'a> Test<'a> {
pub fn new() -> Self {
Test { d: PhantomData }
}
pub fn test(&'a self) {}
}
fn main() {
let t = Arc::new(Test::new());
let t2 = t.clone();
std::thread::spawn(move || {
t2.test();
});
}
这无法编译并出现以下错误
error[E0597]: `t2` does not live long enough
--> src/main.rs:21:9
|
19 | let t2 = t.clone();
| -- lifetime `'1` appears in the type of `t2`
20 | std::thread::spawn(move || {
21 | t2.test();
| ^^-------
| |
| borrowed value does not live long enough
| argument requires that `t2` is borrowed for `'1`
22 | });
| - `t2` dropped here while still borrowed
我猜编译器认为t2
在调用test()
. 似乎如果我将d
字段的类型修改为struct Test
不包括 的任何内容Mutex
,例如d: Option<&'a u8>
,它就可以正常工作。Mutex 有什么特别之处,因为它只是一个UnsafeCell
?
解决方案
Mutex 有什么特别之处,因为它只是一个
UnsafeCell
?
差异是方差。
&'a T
在生命周期中是协变'a
的:您可以将具有较长生命周期的不可变引用强制转换为具有严格较短生命周期的引用,因为通过预期的&'long T
地方总是安全的。&'short T
这就是为什么代码在没有UnsafeCell
.
但是它UnsafeCell<&'a T>
是不变的,'a
因为它具有内部可变性:如果您可以传递UnsafeCell<&'long T>
给需要的代码UnsafeCell<&'short T>
,那么该代码可以将短期引用写入您的长期单元格。UnsafeCell
所以强迫一个人过不同的生活是不安全的。
(任何允许你改变它包含的引用的类型也是如此,例如Mutex<&'a T>
or &mut &'a T
。)
推荐阅读
- javascript - 如何将我的变量从模板传递到views.py
- javascript - 如何让子组件控制根组件中的反应钩子
- visual-studio-code - 在 vscode 预览窗口中转到定义会破坏编辑器
- facebook - 自定义内部 Facebook App Graph API 不返回页面的帖子评论
- linq - Azure 数据资源管理器 (Kusto) 查询转换器是否存在现有表达式?
- swift - 为什么 ViewDidLoad 中的这段代码没有执行?
- r - 传播非常长的数据集 - 性能问题
- apache-spark - 火花重试尝试配置在火花会话中不起作用
- tableau-api - 有没有办法让字段标签成为 Tableau 中的筛选器?
- laravel - Laravel Nova - 保存新寄存器时数据丢失