前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Rust并发控制之Barrier

Rust并发控制之Barrier

作者头像
newbmiao
发布2023-11-27 12:32:16
1940
发布2023-11-27 12:32:16
举报
文章被收录于专栏:学点Rust学点Rust

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 来实现的。这种组合也是一种有意思的并发控制方式,下次我们再聊聊它们。

推荐阅读

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

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

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2023-11-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 菜鸟Miao 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档