【发布时间】:2022-08-23 20:00:55
【问题描述】:
情况
- 我有一个 f32 数组
- 我有一些线程,每个线程都会改变数组的一小部分
- 我不知道哪些索引会被改变
- 每个线程都必须锁定数组,然后花费一些时间进行昂贵的计算
- 之后,它会改变索引并释放数组
- 看看下面注释的最小示例
问题
第一个线程将锁定数组,其他线程不能再编辑它。从而浪费了很多时间。需要编辑不同索引并且永远不会触及第一个线程所需的索引的其他线程可以同时执行。
可能的解决方案
- 我知道数组的寿命比所有线程都长,所以不安全的 Rust 是一个可行的选择
- 我已经为可能有相同问题的其他人发布了一个使用 2 个外部 crate 的解决方案。
- 您可能会想出一个仅限 stdlib 的解决方案。
最小的例子:
use std::sync::{Arc, Mutex};
use std::thread;
use std::time::Duration;
use rand::Rng;
fn main() {
// Store the mutex
let container = Arc::new(Mutex::new([0.0; 10]));
// This will keep track of the created threads
let mut threads = vec![];
// Create new Threads
for _ in 0..10 {
// Create a copy of the mutex reference
let clone = Arc::clone(&container);
threads.push(thread::spawn(move || {
// The function somehow calculates the index that has to be changed
// In our case its simulated by picking a random index to emphasize that we do not know the index
let mut rng = rand::thread_rng();
let index = rng.gen_range(0..10);
// Unfortuantely we have to lock the array before the intense calculation !!!
// If we could just lock the index of the array, other threads could change other indices in parallel
// But now all of them need to wait for the lock
let mut myarray = clone.lock().unwrap();
// simulate intense calculation
thread::sleep(Duration::from_millis(1000));
// Now the index can be changed
println!(\"Changing index {}\", index);
myarray[index] += 1.0;
}));
}
// Wait for all threads to finish
for thread in threads {
thread.join().unwrap();
}
// I know that myarray outlives the runtime of all threads.
// Therefore someone may come up with an unsafe solution
// Print the result
println!(\"{:?}\", container);
}
标签: multithreading rust