gpt4 book ai didi

multithreading - 如何在不使用跟踪句柄的情况下等待未知数量的 Rust 线​​程完成?

转载 作者:行者123 更新时间:2023-11-29 08:08:39 26 4
gpt4 key购买 nike

有哪些好的方法可以使这个 Barrier 示例处理两个差异:

  1. 事先不知道项目的数量(例如,在将大文件拆分为行的情况下)

  2. 不跟踪线程句柄(例如,不使用下面示例中的 handles 向量)。动机是这样做会增加额外的开销。

示例代码:

use std::sync::{Arc, Barrier};
use std::thread;

let mut handles = Vec::with_capacity(10);
let barrier = Arc::new(Barrier::new(10));
for _ in 0..10 {
let c = barrier.clone();
handles.push(thread::spawn(move|| {
// do some work
c.wait();
}));
}
// Wait for other threads to finish.
for handle in handles {
handle.join().unwrap();
}

代码片段略微改编自 Barrier docs .

我想到的第一件事是(如果可能的话)改变 Barrier 的内部值;但是,API 不提供对 Barrier 结构的 num_threads 属性的可变访问。

另一个想法是不使用 Barrier 而是使用 AtomicUsize 编写自定义逻辑。

我愿意学习在 Rust 中使用最符合人体工程学/最惯用的方法来做到这一点。

最佳答案

您可以在原子上使用自旋锁来等待所有线程退出。当然,你可以传递 Arc<AtomicUsize> 而不是使用 static atomic进入每个线程。

Ordering::SeqCst可能太强了,但并发编程很难,我不确定如何放宽这种顺序。

虽然可以通过这种方式完成,但创建线程的成本可能会使微优化相形见绌。同样值得考虑的是,繁忙的等待会降低程序的性能。

use std::panic;
use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT};
use std::thread;
use std::time::Duration;

static GLOBAL_THREAD_COUNT: AtomicUsize = ATOMIC_USIZE_INIT;

fn main() {
for i in 0..10 {
// mark that the thread is about to run
// we need to do it in the main thread to prevent spurious exits
GLOBAL_THREAD_COUNT.fetch_add(1, Ordering::SeqCst);
thread::spawn(move|| {
// We need to catch panics to reliably signal exit of a thread
let result = panic::catch_unwind(move || {
// do some work
println!("{}-th thread reporting", i+1);
});
// process errors
match result {
_ => {}
}
// signal thread exit
GLOBAL_THREAD_COUNT.fetch_sub(1, Ordering::SeqCst);
});
}
// Wait for other threads to finish.
while GLOBAL_THREAD_COUNT.load(Ordering::SeqCst) != 0 {
thread::sleep(Duration::from_millis(1));
}
}

Playground link

关于multithreading - 如何在不使用跟踪句柄的情况下等待未知数量的 Rust 线​​程完成?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44916445/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com