一笔可变借款和多笔不可变借款

戴维·佩德森

我正在尝试编写一个程序,该程序产生一个后台线程,该线程不断将数据插入某些集合中。同时,我想继续从中获取输入,stdin并检查该输入是否在线程正在操作的集合中。

这是一个简单的例子:

use std::collections::HashSet;
use std::thread;

fn main() {
    let mut set: HashSet<String> = HashSet::new();

    thread::spawn(move || {
        loop {
            set.insert("foo".to_string());
        }
    });

    loop {
        let input: String = get_input_from_stdin();

        if set.contains(&input) {
            // Do something...
        }
    }
}

fn get_input_from_stdin() -> String {
    String::new()
}

但是,由于所有权问题,这不起作用。

我仍然对Rust还是陌生的,但这似乎应该可以实现。我只是找不到Arcs,Rcs,Mutexes等的正确组合来包装数据。

马修M.

首先,请阅读有关Rust单元格和引用计数类型的Need整体说明


这里有两个问题要解决:

  1. 在线程之间共享所有权,
  2. 可变别名。

要共享所有权,最简单的解决方案是Arc它要求它的参数Sync(可以从多个线程安全地访问),可以Send通过将其包装在Mutex或中来实现任何类型的参数RwLock

为了在存在可变性的情况下安全地获得别名,两者MutexRwLock都会起作用。如果您有多个阅读器,则RwLock可能会有额外的性能优势。由于您只有一个读者,所以没有意义:让我们使用simple Mutex

因此,您的类型是:Arc<Mutex<HashSet<String>>>

下一个技巧是将值传递给闭包以在另一个线程中运行。该值已移动,因此您需要创建的克隆,Arc然后再传递该克隆,否则,您已移动了原始文件,无法再访问它。

最后,访问数据需要进行借阅和锁定。

use std::sync::{Arc, Mutex};

fn main() {
    let set = Arc::new(Mutex::new(HashSet::new()));

    let clone = set.clone();
    thread::spawn(move || {
        loop {
            clone.lock().unwrap().insert("foo".to_string());
        }
    });

    loop {
        let input: String = get_input_from_stdin();

        if set.lock().unwrap().contains(&input) {
            // Do something...
        }
    }
}

unwrap那里的呼叫是因为Mutex::lock返回ResultMutex如果中毒了,就不可能将其锁定,这意味着在锁定时发生了恐慌,因此其内容可能是垃圾。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章