一个可变借用和多个不可变借用

Dav*_*sen 3 concurrency multithreading ownership rust

我正在尝试编写一个程序,它生成一个后台线程,不断地将数据插入到某个集合中.同时,我想继续获取输入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()
}
Run Code Online (Sandbox Code Playgroud)

但是由于所有权的原因,这不起作用.

我还是Rust的新手,但这似乎应该是可行的.我只是找不到正确的Arcs,Rcs,Mutexes等组合来包装我的数据.

Mat*_* M. 6

首先,请阅读需要关于Rust的细胞和参考计数类型的整体解释.


这里有两个问题需要解决:

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

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

为了安全地获得混叠的可变性的存在,都MutexRwLock正常工作.如果您有多个读者,RwLock可能会有额外的性能优势.既然你有一个读者就没有意义了:让我们使用简单的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...
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

呼叫unwrap是因为Mutex::lock返回a Result; Mutex如果它被毒害,可能无法锁定它,这意味着当它被锁定时发生恐慌,因此其内容可能是垃圾.