我正在尝试开始使用 Rust 线程。在我的示例中(人为设计但基于实际问题),我想接受一个只读HashMap作为函数的参数,然后将其提供给多个线程,每个线程都从它的分区中读取。
use std::{
collections::HashMap,
sync::{mpsc::channel, Arc},
thread,
};
const THREADS: u32 = 10;
// Concurrently add the lengths of values.
pub fn concurrent_lens(inputs: &HashMap<u32, String>) -> usize {
let inputs_arc = Arc::new(inputs);
let (tx, rx) = channel();
// Count length of all strings in parallel.
// Each thread takes a partition of the data.
for thread_i in 0..THREADS {
let tx = tx.clone();
let inputs_clone = inputs_arc.clone();
thread::spawn(move || {
for (i, content) in inputs_clone.iter() {
// Only look at my partition's keys.
if (i % THREADS) == thread_i {
// Something expensive with the string.
let expensive_operation_result = content.len();
tx.send(expensive_operation_result).unwrap();
}
}
});
}
// Join and sum results.
let mut result = 0;
for len in rx.iter() {
result += len;
}
result
}
Run Code Online (Sandbox Code Playgroud)
但是,编译器说:
use std::{
collections::HashMap,
sync::{mpsc::channel, Arc},
thread,
};
const THREADS: u32 = 10;
// Concurrently add the lengths of values.
pub fn concurrent_lens(inputs: &HashMap<u32, String>) -> usize {
let inputs_arc = Arc::new(inputs);
let (tx, rx) = channel();
// Count length of all strings in parallel.
// Each thread takes a partition of the data.
for thread_i in 0..THREADS {
let tx = tx.clone();
let inputs_clone = inputs_arc.clone();
thread::spawn(move || {
for (i, content) in inputs_clone.iter() {
// Only look at my partition's keys.
if (i % THREADS) == thread_i {
// Something expensive with the string.
let expensive_operation_result = content.len();
tx.send(expensive_operation_result).unwrap();
}
}
});
}
// Join and sum results.
let mut result = 0;
for len in rx.iter() {
result += len;
}
result
}
Run Code Online (Sandbox Code Playgroud)
我的选择是,据我所知:
inputs静态。这是不可能的,因为它不是静态数据。input(而不是引用)。所以我的功能是pub fn concurrent_lens(inputs: HashMap<u32, String>) -> usize. 这让编译器对它的生命周期感到满意,但数据存在于函数之外,并且在外部具有更长的生命周期。pub fn concurrent_lens(inputs: Arc<HashMap<u32, String>>) -> usize。这工作正常,但似乎是一个真正有漏洞的抽象,因为调用代码不应该知道它正在调用一个使用并发的函数。这些似乎都不对。我错过了什么吗?