一个可变借用和多个不可变借用
One mutable borrow and multiple immutable borrows
我正在尝试编写一个生成后台线程的程序,该线程不断地将数据插入某个集合。同时,我想继续从 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 等的正确组合来包装我的数据。
首先,请阅读。
这里有两个问题需要解决:
- 在线程之间共享所有权,
- 可变别名。
要共享所有权,最简单的解决方案是Arc
。它要求其参数为 Sync
(可从多个线程安全访问),这可以通过将任何 Send
类型包装在 Mutex
或 RwLock
.[=27 中来实现=]
为了在存在可变性的情况下安全地获得别名,Mutex
和 RwLock
都可以。如果您有多个 reader,RwLock
可能会有额外的性能优势。由于您只有一个 reader 没有意义:让我们使用简单的 Mutex
.
因此,您的类型是:Arc<Mutex<HashSet<String>>>
。
下一个技巧是将闭包的值传递给另一个线程中的 运行。该值为 moved,因此您需要 first 克隆 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
returns a Result
;如果Mutex
中毒,可能无法锁定,这意味着锁定时发生了恐慌,因此其内容可能是垃圾。
我正在尝试编写一个生成后台线程的程序,该线程不断地将数据插入某个集合。同时,我想继续从 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 等的正确组合来包装我的数据。
首先,请阅读
这里有两个问题需要解决:
- 在线程之间共享所有权,
- 可变别名。
要共享所有权,最简单的解决方案是Arc
。它要求其参数为 Sync
(可从多个线程安全访问),这可以通过将任何 Send
类型包装在 Mutex
或 RwLock
.[=27 中来实现=]
为了在存在可变性的情况下安全地获得别名,Mutex
和 RwLock
都可以。如果您有多个 reader,RwLock
可能会有额外的性能优势。由于您只有一个 reader 没有意义:让我们使用简单的 Mutex
.
因此,您的类型是:Arc<Mutex<HashSet<String>>>
。
下一个技巧是将闭包的值传递给另一个线程中的 运行。该值为 moved,因此您需要 first 克隆 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
returns a Result
;如果Mutex
中毒,可能无法锁定,这意味着锁定时发生了恐慌,因此其内容可能是垃圾。