我正在使用Rust Axum作为我的Web框架.

我希望在我的路由处理程序中使用DO可变共享状态.我遇到了这样一个问题:

https://github.com/tokio-rs/axum/discussions/629

它指向了这个例子:

https://github.com/tokio-rs/axum/blob/dea36db400f27c025b646e5720b9a6784ea4db6e/examples/key-value-store/src/main.rs

在给国家读书写信的时候,我在不同的地方关注着unwrap()人:

let db = &state.read().unwrap().db;

state.write().unwrap().db.insert(key, bytes);

我以为unwrap()美元是个糟糕的练习?

我也觉得真的不会有任何情况(我能想到的)当解包可能失败.但也许我错过了什么?在什么情况下,这unwrap家公司会失败?

在上面的示例上下文中使用unwrap()是否安全?

推荐答案

TL;DR:是的,MutexRwLock锁定到unwrap()就可以了.

STD的MutexRwLock实现poisoning:如果线程在持有锁(RwLock的写锁)时死机,则锁变为poisoned.任何进一步的锁定try 都将返回Err(PoisonError).这就是锁定操作返回Result的原因.

这样做的原因是,假定数据具有应该始终保持的不变量.代码可能会暂时 destruct 不变量,然后在此之后恢复它们.但是,如果代码意外死机,不变量可能仍处于损坏状态,进一步判断数据的代码可能会发现数据处于无效状态,并产生错误的结果(或死机).这与the unwind safety traits的存在是相同的原因.

通常,这不是问题,因为如果代码死机,调用它的代码也会死机(解压或中止),数据将完全无法访问.但有两种情况是有问题的:当您捕捉到异常(上面提到的展开安全)时,以及当您从不同的线程访问数据时,因为死机的线程不会导致另一个线程死机(在展开模式下).这就是在这种情况下锁被下毒的原因,以防止您看到损坏的数据.

有时,您需要处理panic 并恢复不变量,或者优雅地退出.但在大多数情况下,当另一个线程死机并使数据成为垃圾时,您也希望在不访问它的情况下也发生panic .这就是unwrap()的所作所为:它在这种情况下会panic .

因为只有当另一个线程在持有锁的时候出现panic 时,它才会死机,所以只有在已经发生死机的情况下,它才会死机.因此,尽管在铁 rust 中通常不鼓励panic ,但在这种情况下,它们是好的.

Rust相关问答推荐

如何从Rust记录WASM堆内存使用情况?

Box::new()会从一个堆栈复制到另一个堆吗?

如何实现泛型枚举的`Serde::Desialize`特性

将PathBuf转换为字符串

如何将映射反序列化为具有与键匹配的字段的定制 struct 的向量?

在 Rust 中用问号传播错误时对类型转换的困惑?

找不到 .has_func 或 .get_func 的 def

Rust 中的静态引用

Rust ECDH 不会产生与 NodeJS/Javascript 和 C 实现相同的共享密钥

当锁被释放时,将锁包装到作用域中是否会发生变化?

无法将`&Vec>`转换为`&[&str]`

当在lambda中通过引用传递时,为什么会出现终身/类型不匹配错误?

Rust中的标记特征是什么?

一个函数调用会产生双重borrow 错误,而另一个则不会

为什么数组不像向量那样在 for 块之后移动?

在 Rust 中,为什么整数溢出有时会导致编译错误或运行时错误?

Rust 中的let是做什么的?

匹配结果时的简洁日志(log)记录

火箭整流罩、tokio-scheduler 和 cron 的生命周期问题

为什么这里需要类型注解?