我正在尝试编写一个程序,该程序产生一个后台线程,该线程不断将数据插入某些集合中。同时,我想继续从中获取输入,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还是陌生的,但这似乎应该可以实现。我只是找不到Arc
s,Rc
s,Mutex
es等的正确组合来包装数据。
首先,请阅读有关Rust单元格和引用计数类型的Need整体说明。
这里有两个问题要解决:
要共享所有权,最简单的解决方案是Arc
。它要求它的参数Sync
(可以从多个线程安全地访问),可以Send
通过将其包装在Mutex
或中来实现任何类型的参数RwLock
。
为了在存在可变性的情况下安全地获得别名,两者Mutex
和RwLock
都会起作用。如果您有多个阅读器,则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
返回Result
;Mutex
如果中毒了,就不可能将其锁定,这意味着在锁定时发生了恐慌,因此其内容可能是垃圾。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句