我在写一些东京的异步码.我有一个多索引数据 struct ,将用户放在我想用粗粒度锁保护他们的位置(与每个对象锁相反).我有这样的东西:
use tokio::sync::RwLock;
struct User {
id: u64,
name: String,
}
// This class is not thread-safe.
struct UserDb {
by_id: HashMap<u64, Arc<RefCell<User>>>,
by_name: HashMap<String, Arc<RefCell<User>>>,
}
impl UserDb {
pub fn add_user(&mut self, name: String) -> Result<(), Error> {
// ...
}
}
// This class is thread-safe.
struct AsyncDb {
users: RwLock<UserDb>,
}
impl AsyncDb {
pub async fn add_user(&self, name: String) -> Result<(), Error> {
self.users.write().await.add_user(name)
}
}
// QUESTION: Are these safe?
unsafe impl Send for AsyncDb {}
unsafe impl Sync for AsyncDb {}
最后没有Send
和Sync
特征,编译器就会抱怨RefCell<User>
不是Send
和Sync
(合理地说是这样),因此通过AsyncDb::add_user
访问/修改是不安全的.
我的解决方案是为数据 struct 实现Send
和Sync
,因为在UserDb
附近的AsyncDb
中有一个粗粒度的锁,其中包含上述RefCell
.
这是一个正确的解决方案吗?它是否违反了任何不变量?有没有更好的办法来处理这件事?
注:这里是铁 rust 初学者.我可能有很多概念上的差距,所以如果事情没有意义,请说出来.