【发布时间】:2022-12-04 03:38:05
【问题描述】:
我已经编写了以下仅使用原子的 Barrier 实现:
use std::sync::atomic::{AtomicUsize, Ordering};
pub struct Barrier {
pub done: AtomicUsize,
pub tids: usize,
}
impl Barrier {
pub fn new(tids: usize) -> Barrier {
Barrier {
done: AtomicUsize::new(0),
tids,
}
}
pub fn wait(&self) {
let done = self.done.fetch_add(1, Ordering::SeqCst);
if done + 1 == self.tids {
self.done.store(0, Ordering::SeqCst);
} else {
while self.done.load(Ordering::SeqCst) != 0 {}
}
}
}
它没有按预期工作。例如,
// inside threads loop
barrier.wait();
println!("a");
barrier.wait();
println!("b");
直觉上,它应该可以工作,因为一旦调用.wait(),它就会挂在while循环上,在所有线程调用.wait()后摆脱它,并为下一个.wait()重置计数器。相反,它最终会挂起。下面是一个用法示例:
fn main() {
println!("Hello, world!");
let barrier = &Barrier::new(10);
std::thread::scope(|s| {
for tid in 0 .. 10 {
s.spawn(move || {
loop {
barrier.wait();
println!("{} a", tid);
barrier.wait();
println!("{} b", tid);
}
});
}
});
}
【问题讨论】:
-
@cafce25 添加了一个用法示例并修复了问题上的问题。
-
编辑:哦,我现在可以看到问题了。它会挂起,因为在另一个线程从循环中退出之前,一个线程可能会增加下一个
.wait()的计数器。愚蠢的。不过,我会保留这个问题。
标签: multithreading rust barrier