如何锁定Rust数据结构的内部结构?

时间:2016-03-16 15:20:47

标签: data-structures collections concurrency rust

我正在尝试实现一个在向量和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();
}

1 个答案:

答案 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();
}

请注意,MutexGuard还会实施DerefDerefMut,这样就可以让他们看到&#34;喜欢锁定类型。