如何锁定Rust数据结构的内部? [英] How can I lock the internals of my Rust data structure?

查看:74
本文介绍了如何锁定Rust数据结构的内部?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试实现一个将值存储在矢量和哈希图中的集合,这就是我到目前为止所拥有的:

I'm trying to implement a collection that stores values in both a vector and a hashmap and this is what I have so far:

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有,但我不知道如何使用它.当我寻找问题时,我只发现用例中人们产生了一堆线程并进行同步.我正在寻找类似的东西:

I obviously need some kind of lock. I've looked at the Mutex Rust has, but I do not understand how to use it. When I search for the problem, I only find use cases where people spawn a bunch of threads and synchronize them. I'm looking for something like:

try {
    lock.lock();
    // insert into both collections
} finally {
    lock.unlock();
}

推荐答案

我显然需要某种锁

I obviously need some kind of lock

我不知道我是否同意这种需求.当多个线程可以同时修改对象时,我只会引入一个锁.请注意,这是两个条件:多线程和并发修改.

I don't know that I agree with this need. I'd only introduce a lock when multiple threads could be modifying the object concurrently. Note that's two conditions: multiple threads AND concurrent modification.

如果只有一个线程,那么Rust对一个项目的单个可变引用的实施将防止出现任何问题.同样,如果您有多个线程并在它们之间完全转移了该项目的所有权,则不需要任何锁定,因为只有一个线程可以对其进行变异.

If you only have one thread, then Rust's enforcement of a single mutable reference to an item will prevent any issues. Likewise, if you have multiple threads and fully transfer ownership of the item between them, you don't need any locking because only one thread can mutate it.

我正在寻找类似的东西:

I'm looking for something like:

try {
    lock.lock();
    // insert into both collections
} finally {
    lock.unlock();
}

如果您需要类似的东西,则可以创建一个 Mutex<()> —一种互斥体,该互斥体锁定单元类型,不占用空间:

If you need something like that, then you can create a Mutex<()> — a mutex that locks the unit type, which takes no space:

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).

Note that there is no explicit unlock required. When you call lock, you get back a MutexGuard. This type implements Drop, which allows for code to be run when it goes out of scope. In this case, the lock will be automatically released. This is commonly called Resource Acquisition Is Initialization (RAII).

在大多数情况下,我不建议您这样做.通常最好包装要锁定的项目.这样可以强制只有在锁定状态下,才能 访问该项目:

I wouldn't recommend this practice in most cases. It's generally better to wrap the item that you want to lock. This enforces that access to the item can only happen when the lock is locked:

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 还实现了 Deref DerefMut ,使它看起来"像锁定类型.

Note that the MutexGuard also implements Deref and DerefMut, which allow it to "look" like the locked type.

这篇关于如何锁定Rust数据结构的内部?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆