我正在尝试实现一个在向量和hashmap中存储值的集合,这是我到目前为止所拥有的:
pub struct CollectionWrapper {
items: Vec<Item>,
items_map: HashMap<ItemKey, Item>,
}
impl CollectionWrapper {
pub fn new() -> Self {
CollectionWrapper {
items: Vec::new(),
items_map: HashMap::new(),
}
}
pub fn add(&mut self, item: Item) {
let key = item.get_key();
self.items.push(item.clone());
self.items_map.insert(key, item.clone());
}
}
我显然需要某种锁定。我看过Mutex
Rust有,但我不明白如何使用它。当我搜索问题时,我只找到人们产生一堆线程并同步它们的用例。我正在寻找类似的东西:
try {
lock.lock();
// insert into both collections
} finally {
lock.unlock();
}
答案 0 :(得分:2)
我显然需要某种锁
我不知道我同意这种需要。当多个线程可以同时修改对象时,我只引入一个锁。请注意以下两个条件:多线程和并发修改。
如果您只有一个主题,那么Rust对项目的单个可变引用的强制执行将防止出现任何问题。同样,如果你有多个线程并在它们之间完全转移项目的所有权,你就不需要任何锁定,因为只有一个线程可以改变它。
我正在寻找类似的东西:
try { lock.lock(); // insert into both collections } finally { lock.unlock(); }
如果您需要类似的东西,那么您可以创建一个Mutex<()>
- 一个锁定单位类型的互斥锁,它不占用空间:
use std::sync::Mutex;
struct Thing {
lock: Mutex<()>,
nums: Vec<i32>,
names: Vec<String>,
}
impl Thing {
fn new() -> Thing {
Thing {
lock: Mutex::new(()),
nums: vec![],
names: vec![],
}
}
fn add(&mut self) {
let _lock = self.lock.lock().unwrap();
// Lock is held until the end of the block
self.nums.push(42);
self.names.push("The answer".to_string());
}
}
fn main() {
let mut thing = Thing::new();
thing.add();
}
请注意,不需要明确的unlock
。当您致电lock
时,您会收到MutexGuard
。此类型实现Drop
,允许代码在超出范围时运行。在这种情况下,锁将自动释放。这通常称为资源获取初始化(RAII)。
在大多数情况下,我不推荐这种做法。包装要锁定的项目通常会更好。这会强制锁定锁定时仅会发生对该项目的访问:
use std::sync::Mutex;
struct Thing {
nums: Vec<i32>,
names: Vec<String>,
}
impl Thing {
fn new() -> Thing {
Thing {
nums: vec![],
names: vec![],
}
}
fn add(&mut self) {
self.nums.push(42);
self.names.push("The answer".to_string());
}
}
fn main() {
let thing = Thing::new();
let protected = Mutex::new(thing);
let mut locked_thing = protected.lock().unwrap();
locked_thing.add();
}