我正在使用 Rocket State
,它传递给 HTTP 请求。这个结构包含一个Mutex<DatastoreInstance>
可以访问 SQLite 数据库并被互斥锁锁定以确保读写安全的结构。
pub struct DatastoreInstance {
conn: Connection,
}
当DatastoreInstance
结构看起来像这样时,只有一个 SQLite 连接一切正常,但我还想在这个结构中添加一个事务对象:
pub struct DatastoreInstance {
conn: Connection,
events_transaction: Transaction,
}
这没有编译,因为Transaction
对象需要引用一个Connection
应该具有它知道的生命周期的对象。我正在使用的 rusqlite 中的Connection
and对象定义如下:Transaction
pub struct Connection {
db: RefCell<InnerConnection>,
cache: StatementCache,
path: Option<PathBuf>,
}
pub struct Transaction<'conn> {
conn: &'conn Connection,
drop_behavior: DropBehavior,
}
为了解决生命周期问题,我必须添加这些生命周期参数才能使其正常工作:
pub struct DatastoreInstance<'a> {
conn: Connection,
events_transaction: Transaction<'a>,
}
这是结果,应该根据我对生命周期和互斥锁的理解工作,但现在我得到一个编译器错误告诉我:
`std::cell::RefCell<lru_cache::LruCache<std::string::String, rusqlite::raw_statement::RawStatement>>` cannot be shared between threads safely
|
= help: within `rusqlite::Connection`, the trait `std::marker::Sync` is not implemented for `std::cell::RefCell<lru_cache::LruCache<std::string::String, rusqlite::raw_statement::RawStatement>>`
= note: required because it appears within the type `rusqlite::cache::StatementCache`
= note: required because it appears within the type `rusqlite::Connection`
= note: required because of the requirements on the impl of `std::marker::Send` for `&rusqlite::Connection`
= note: required because it appears within the type `datastore::DatastoreInstance<'_>`
= note: required because of the requirements on the impl of `std::marker::Send` for `std::sync::Mutex<datastore::DatastoreInstance<'_>>`
= note: required because it appears within the type `endpoints::ServerState<'_>`
= note: required by `rocket::State`
根据我对互斥体的理解,这段代码应该是有效的,因为整个DatastoreInstance
结构都被包裹在一个Mutex
应该保证一次只有一个线程引用这个对象的情况下。
我错过了什么?
为什么编译器在 a 内引用而不是仅在 a内引用RefCell
后发现不再安全?Connection
Transaction
Connection
我对互斥锁的工作原理有不好的理解吗?我的生命周期是否无效并以某种方式破坏了读/写安全?将Connection
andTransaction
放在同一个结构中的设计是否会破坏读/写安全性?我是否需要以某种方式重新设计我的数据结构以确保安全?还是我只是错过了一些非常明显的东西?