Rust并发控制之Barrier

2023-11-27 12:32:16 浏览数 (1)

Rust 有很多种控制并发的方式,Barrier(屏障)是其中一种用来同步多线程计算的方式。

今天拿代码来简单看下。

比如我们要多线程计算,期望所有线程都计算完毕再输出最终结果。常规多线程代码示例可以用线程 join 来等待

代码语言:javascript复制
use std::sync::{Arc, Mutex};

fn main() {
    let numthreads = 10;
    let my_mutex = Arc::new(Mutex::new(0));
    let mut handlers = Vec::with_capacity(numthreads);

    for _ in 0..numthreads {
        let my_lock = my_mutex.clone();
        handlers.push(std::thread::spawn(move || {
            let mut guard = my_lock.lock().unwrap();
            *guard  = 1;
        }));
    }
    for handler in handlers {
        handler.join().unwrap();
    }

    let answer = { *my_mutex.lock().unwrap() };
    assert_eq!(answer, numthreads);
}

而如果用 Barrier,我们可以这么写:

代码语言:javascript复制
use std::sync::{Arc, Barrier, Mutex};

fn main() {
    let numthreads = 10;
    let my_mutex = Arc::new(Mutex::new(0));

    // We use a barrier to ensure the readout happens after all writing
    let barrier = Arc::new(Barrier::new(numthreads   1));

    for i in 0..numthreads {
        let my_barrier = barrier.clone();
        let my_lock = my_mutex.clone();
        std::thread::spawn(move || {
            let mut guard = my_lock.lock().unwrap();
            *guard  = 1;

            // Release the lock to prevent a deadlock
            drop(guard);
            println!("thread {} is ready", i);
            // Blocks the current thread until all threads have rendezvoused here.
            my_barrier.wait();
            println!("thread {} is done", i)
        });
    }

    // A barrier will block `n`-1 threads which call [`wait()`] and then wake
    // up all threads at once when the `n`th thread calls [`wait()`].
    barrier.wait();

    let answer = { *my_mutex.lock().unwrap() };
    assert_eq!(answer, numthreads);
}

Barrier 可以用 wait 来控制 n 个线程的同步,数量需要提前指明。当调用 wait 时,如果不是第 n 个,就会一直阻塞当前线程,直到第 n 个 wait 调用,才能进行后续操作。

这种机制就像在多个线程中插入了一道屏障,当所有线程都执行到这里时,才能解除屏障继续向后执行。

当然这样实现相较于第一种,在线程数量大的时候也是会有比较明显的性能开销的,底层是使用 condvar mutex 来实现的。这种组合也是一种有意思的并发控制方式,下次我们再聊聊它们。

推荐阅读

  • 掌握Rust:从零开始的所有权之旅
  • 聊聊Rust的Cell和RefCell
  • 聊聊共享所有权之Rc和Arc
  • 聊聊Rust的并发约束:Send和Sync

如果有用,点个 在看,让更多人看到

外链不能跳转,戳 阅读原文 查看参考资料

0 人点赞