产生100个线程并增加一个共享计数器,这可以优化/改进到在1秒内完成吗



我想学习如何在Rust中编写Go代码,Go代码在这里供参考:https://go.dev/play/p/j9osOG5xs1R

它基本上启动100个线程,在每个线程中循环1000次,每次迭代睡眠1毫秒,还增加一些共享状态。

由于它睡眠时间为1毫秒,因此应该在1秒内完成。

在我的Go版本中,我实际上创建了100个线程,它在大约1秒内完成,正如预期的那样。

我的铁锈代码目前只有10个线程,需要10秒才能完成。

我一定做错了什么,有什么提高表现的建议吗

use std::sync::{Arc, Mutex};
use std::thread;
use std::time::Duration;
fn main() {
let counter = Arc::new(Mutex::new(0));
let mut handles = vec![];
use std::time::Instant;
let now = Instant::now();
for _ in 0..10 {
let counter = Arc::clone(&counter);
let handle = thread::spawn(move || {
let mut num = counter.lock().unwrap();
for _ in 0..1000 {
thread::sleep(Duration::from_millis(1));
*num += 1;
}
});
handles.push(handle);
}
for handle in handles {
handle.join().unwrap();
}
println!("Result: {}", *counter.lock().unwrap());
let elapsed = now.elapsed();
println!("Elapsed: {:.2?}", elapsed);
}

我甚至在发布模式下构建了这个程序:

cargo build --release
./target/release/spawner

出于某种原因,仅10个线程就需要超过10秒。。。

每个线程在运行的整个1秒内锁定counter,阻止所有线程取得任何进展。这会导致它们按顺序运行,而不是并行运行。

如果你缩小了锁的范围,那么他们会在每毫秒内获取并释放互斥锁,解除彼此的锁定,并允许程序在预期的1秒内完成。

let handle = thread::spawn(move || {
for _ in 0..1000 {
thread::sleep(Duration::from_millis(1));
let mut num = counter.lock().unwrap();
*num += 1;
}
});

输出:

Result: 10000
Elapsed: 1.09s

相关内容

最新更新