当前位置: 首页 > news >正文

Rust教程6:并发编程和线程通信

文章目录

    • 线程初步
    • join方法
    • 线程通信

Rust系列:初步⚙所有权⚙结构体和枚举类⚙函数进阶⚙泛型和特征

线程初步

在Rust中,开启多线程进行并发编程,只需调用thread::spawn,但这里有一个坑点,即spawn函数只有一个传入参数,即准备运行的函数,原则上讲这个准备并发执行的函数并没有输入参数。但从测试的角度来说,这样就没法分清谁是谁,为了让带有参数的函数也能享受多线程功能,可采取闭包的方式,将其转化为无参数函数,示例如下。

use std::thread;
use std::time::Duration;

fn count(s:String){
    for i in 0..3{
        thread::sleep(Duration::from_millis(100));
        println!("{},{}", s, i);
    }
}

fn main() {
    thread::spawn(|| -> count("A".to_string()));
    count("B".to_string())
}

其中,count的功能是,每隔100毫秒输出一个数字。在主函数中,调用了两次count,第一次开启了线程开关,第二次则在main的主线程中运行,结果如下,二者在输出上是没有先后顺序的,说明的确在并发执行。

B,0
A,0
B,1
A,1
A,2
B,2

join方法

如果讲上面代码的主函数改为调用两次spawn,像下面这样,那么运行之后,将不会有任何输出。原因也很简单,每一个线程开启之后,都会等待100毫秒才开始输出数字,但主线程却早早结束了。

fn main() {
    thread::spawn(||{count("A".to_string())});
    thread::spawn(||{count("B".to_string())});
}

为了避免这种尴尬的局面,可通过join方法,让主进程等待子进程跑完之后再继续,方法也很简单,只需写成下面的形式

fn main() {
    thread::spawn(||{count("A".to_string())}).join().unwrap();
    thread::spawn(||{count("B".to_string())}).join().unwrap();
}

输出结果如下,发现多线程貌似没起到作用。这个现象并不难理解,由于A线程后面紧跟着join,所以主线程会等待A线程执行完毕再继续。

A,0
A,1
A,2
B,0
B,1
B,2

为了避免这种尴尬的局面出现,可以将线程和join的位置分开,即给线程绑定一个变量,像下面这样,从而运行就正常了。

fn main() {
    let a = thread::spawn(||{count("A".to_string())});
    let b = thread::spawn(||{count("B".to_string())});
    a.join().unwrap();
    b.join().unwrap();
}

线程通信

在Rust中,线程通信需要引入另一个模块,mpsc(multiple producer, single consumer),使用其中的channel函数,生成一对可以穿透线程的电话

use std::thread;
use std::sync::mpsc;

fn main() {
    let (tx, rx) = mpsc::channel();
    thread::spawn(move || {
        for i in 0..3{
            tx.send(i.to_string()).unwrap();
        }
        let val = String::from("hi");
        tx.send(val).unwrap();
    });

    loop{
        let received = rx.recv().unwrap();
        println!("Got: {}", received);
        if received=="hi"{
            return;
        }
    }
}

其中,tx在子线程中通过send进行发送,rx在主线程中通过recv()接收,运行结果如下

Got: 0
Got: 1
Got: 2
Got: hi

相关文章:

  • 基于pytorch使用特征图输出进行特征图可视化
  • Spring Boot 校验用户上传的图片文件
  • 【Qt】撤销/恢复的快捷键
  • Git基本概念和使用方式
  • 【MySQL系列】第二章 · SQL(上)
  • Rd-03D串口协议
  • 【Opencv】cv::dnn::NMSBoxes()函数详解
  • 华为云Ascend310服务器使用
  • JVM在线分析-监控工具(jps, jstat, jstatd)
  • 智慧城市建设解决方案分享【完整】
  • 为 Ubuntu 虚拟机构建 SSH 服务器
  • 2023年11月在线IDE流行度最新排名
  • 基于springboot的在线文档管理系统
  • 基于springboot实现桥牌计分管理系统项目【项目源码】计算机毕业设计
  • Android Studio里的C/C++返回: ld: error: undefined symbol
  • 【Go入门】面向对象
  • Vatee万腾科技决策力的未来展望:开创数字化创新的新高度
  • 音视频基础知识
  • Linux之基础开发工具gdb调试器的使用(三)
  • 数据存储_PGSQL
  • 15年全程免费,内蒙古准格尔旗实现幼儿园到高中0学费
  • AI赋能科学红毯,机器人与科学家在虚实之间叩问“科学精神”
  • 北方将现今年首场大范围高温天气,山西河南山东陕西局地可超40℃
  • 中期选举后第三势力成“莎拉弹劾案”关键,菲律宾权斗更趋复杂激烈
  • 韩正会见美国景顺集团董事会主席瓦格纳
  • 小耳朵等来了春天:公益义诊筛查专家走进安徽安庆