【第十课】Rust并发编程(一)

目录

前言

Fork和Join


前言

本节会介绍Rust中的并发编程,并发编程在编程中是提升cpu使用率的一大利器,通过多线程技术提升效率,Rust的并发和其他编程语言的并发不同的地方在于,Rust号称无畏并发。更重要的一点是安全。Rust中所有权机制依然存在于多线程当中。

本节会介绍Rust中并发编程的三种方式

1.Fork和Join

2.通道

3.共享可变状态

我们一个一个来看

Fork和Join

Fork和Join在编程语言中是一种比较常见的并发模式,Fork的意思就是新开线程,Join的意思就是等待线程的结果,这是非常通用的做法,只要任务可以切分,使用Fork和Join的方式往往都会取得比较好的结果。

我们以一个简单的例子来说明,将一个String类型的vector中的元素分别计算字符串的长度,如果串型来做,就for循环vec,分别计算元素的长度,我们使用Fork和Join来实现一下。

下面的代码中,定义了5个元素的vec,在计算前还定义了一个JoinHandle的vec,然后我们循环data,使用的into_iter()表示将元素的所有权转移给迭代器,在for循环内部,使用thread::spawn启动线程,线程执行的任务使用闭包表示,比较特殊的是在闭包的开头,新增了move关键字,这是为了将所有权转移到闭包内,在这里就是循环中的变量ss,最后一个for循环,使用join等待线程执行结束。

rust 复制代码
use std::collections::HashSet;
use std::sync::Arc;
use std::thread;
use std::thread::JoinHandle;

fn main() {
    let data: Vec<String> = vec![
        String::from("hello"),
        String::from("rust"),
        String::from("flink"),
        String::from("kafka"),
        String::from("hadoop"),
    ];


    let mut thread_handles: Vec<JoinHandle<()>> = vec![];

    for ss in data.into_iter() {
      
        thread_handles.push(
            thread::spawn(move || {
                println!("{} length = {}", ss, ss.len());
            
            }));
    }

    for handle in thread_handles {
        handle.join().unwrap();
    }
}

在上面的基础上,我们加上一个小需求来感受一下,Rust的并发安全问题,我们定义一个黑词vec,当处理的词语出现在黑词中时,做特殊输出。如果是别的编程语言,非常简单,只需要让线程读取一个HashSet即可,因为只读,但是在Rust中不行,为什么呢?假设存在这样的一个HashSet,存储黑词,在主线程中定义,那么当所有者离开作用域后,HashSet会被清理,此时如果子线程依然还在读这个HashSet,就会造成问题。那么在Rust中如何解决呢?在Rust中,智能指针Arc允许一个值存在多个所有者,是一个特殊情况,当最后一个所有者离开作用域后,这块内存才会被回收。

下面代码实现了上面的功能,使用了Arc共享了所有者。下面的代码中,我们定义HashSet,并且使用Arc使这个HashSet变成可以共享所有者。并在在每个线程中都有一个变量是所有者,保证了线程读到的HashSet一定是有效的。

rust 复制代码
use std::collections::HashSet;
use std::sync::Arc;
use std::thread;
use std::thread::JoinHandle;

fn main() {
    let data: Vec<String> = vec![
        String::from("hello"),
        String::from("rust"),
        String::from("flink"),
        String::from("kafka"),
        String::from("hadoop"),
    ];

    let mut black_words: HashSet<String> = HashSet::new();
    black_words.insert(String::from("kafka"));

    let black_words_arc: Arc<HashSet<String>> = Arc::new(black_words);

    let mut thread_handles: Vec<JoinHandle<()>> = vec![];

    for ss in data.into_iter() {
        let black_word_temp_arc = Arc::clone(&black_words_arc);
        thread_handles.push(
            thread::spawn(move || {
                if !black_word_temp_arc.contains(&ss) {
                    println!("{} length = {}", ss, ss.len());
                } else {
                    println!("black_word")
                }
            }));
    }

    for handle in thread_handles {
        handle.join().unwrap();
    }
}
相关推荐
考虑考虑4 小时前
cmd局部设置java变量
运维·后端·自动化运维
2601_966949655 小时前
为什么量化策略需要大量历史股票数据?从回测可信度理解数据规模
开发语言·python·数据分析·pandas·量化交易·股票数据·quantdash
niucloud-admin5 小时前
JAVA V6 多商户商城 开发文档——插件目录结构
java·开发语言
滕州市燕猫虎计算机科技工作室个体工商户5 小时前
Java锁
java·开发语言
多加点辣也没关系5 小时前
JavaScript|第31章:表单与控件
开发语言·javascript·ecmascript
菜鸟~noob2336 小时前
【电子战】 第09篇:阵列信号处理——波束形成、MVDR、MUSIC【含matlab代码】
开发语言·matlab·信号处理
ocean21036 小时前
2025-2026年Python面试高频知识点洞察
开发语言·python·面试·python八股文
零依赖极客6 小时前
Day 6·1 ARMv8.2 dotprod——vdotq_s32 一条指令做 4 个点积
c语言·开发语言·人工智能·矩阵·arm·vllm
陈随易7 小时前
在Finch用了62亿词元,我认为这是新一代Agent工具之神
前端·人工智能·后端
新时代牛马8 小时前
cyclictest 毛刺从哪来?从ftrace、latencytop、perf到IRQ/调度延迟定位
android·开发语言·python·kotlin