生成 100 个线程并递增共享计数器,是否可以优化/改进以在 1 秒内完成?

Bla*_*man 2 rust

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

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

由于它休眠 1 毫秒,因此应该在 1 秒内完成。

在我的 Go 版本中,我实际上创建了 100 个线程,并且按预期在大约 1 秒内完成。

我的 Rust 代码目前只有 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);
}
Run Code Online (Sandbox Code Playgroud)

我什至还在发布模式下构建了该程序:

cargo build --release
./target/release/spawner
Run Code Online (Sandbox Code Playgroud)

由于某种原因,只有 10 个线程需要 10 秒以上......

Joh*_*ica 7

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

如果缩小锁的范围,那么它们将每毫秒抓取并释放互斥锁,从而相互解除阻塞并允许程序在预期的 1 秒内完成。

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

输出:

Result: 10000
Elapsed: 1.09s
Run Code Online (Sandbox Code Playgroud)

  • @Blankman 在这种情况下,这是一个 CPU 密集型操作,异步最适合 IO 密集型操作,因此它不会使其更快。 (2认同)