文章目录

  • 前言
  • 一、管道是什么?
  • 二、使用步骤
    • 1.通道类型
    • 2.通道的定义与使用
    • 3.通道中的所有权问题
    • 4.多信息多线程模拟
  • 总结

前言

在结束线程的学习过后,笔者继续学习了关于多线程通信的工具,也就是通道,利用通道实现多种不同类型的多线程之间的通信,也由此引发了一些笔者的思考,具体如下所述。
同样学习视频地址为 ->> b站令狐一冲Rust进阶


一、管道是什么?

Rust中一个实现消息传递并发的主要工具是通道。通道由两部分组成,一个是发送端,一个是接收端,发送端用来发送消息,接收端用来接收消息。发送者或者接收者任一被丢弃时就可以认为通道被关闭了。

二、使用步骤

1.通道类型

1.通过mpsc::channel()创建通道,mpsc 是多个生产者,一个消费者;
2.通过SPMC::channel()创建通道,spmc 是一个生产者,多个消费者;

注意:创建通道后返回的是发送者和接收者(生产者和消费者),示例:

let (tx,rx) = mpsc::channel();
let (tx,rx) = spmc::channel();

在下文中将主要使用多个生产者单个消费者为主要示例

2.通道的定义与使用

代码如下:

use std::thread;
use std::sync::mpsc;fn main() {let (tx, rx) = mpsc::channel();thread::spawn(move || {let val = String::from("hello,thread!");tx.send(val).unwrap();});let received = rx.recv().unwrap();println!("Main thread got {}",received);
}

在上述代码段中,笔者通过 mpsc::channel() 定义了 (tx , rx) ,也就是发送端和接收端,同时创建了一个子线程,在线程中定义了一个String类型的变量并通过 tx 发送端将该变量送入了通道,而在主线程中定义的 rx 接收端就会接收到通道中的变量,最后进行输出,编译运行结果如下:

root@ThinkPad-T540p:~/learn_rust/learn_thread_channel# cargo runCompiling learn_thread_channel v0.1.0 (/root/learn_rust/learn_thread_channel)Finished dev [unoptimized + debuginfo] target(s) in 0.82sRunning `target/debug/learn_thread_channel`
Main thread got hello,thread!

编译运行是顺利的,成功实现了主线程与子线程之间的通信,但是在上篇关于线程的文章中,笔者曾经遇到过子线程还未结束就因为主线程结束而被强制中断的情况,当时使用了 join() 解决了这个问题,但是在这里并未使用join(),但是主线程却一直等待子线程对val变量的发送,这是有违昨天所学的知识的。

而针对该问题,在视频中也得到了答案,是因为接收端rx使用的recv()函数。这里使用的recv()方法,会保持主线程为阻塞态,直到有一个消息到来并接收,所以上述代码段中不需要join()方法,同时也可以使用try_recv()方法,该方法不会阻塞,会立即返回。

3.通道中的所有权问题

在上述通道通信简单使用的代码段中,笔者将String型变量 val 作为发送数据送入了发送通道,而此时也就相当于将val的所有权移动到了该通道中,所以在通道将val发送后,就不能再单独使用val了。

4.多信息多线程模拟

结束上述学习后,除了对于通信的简单实现,还对单个子线程发送多个信息与多个线程发送信息的情况进行了实现,代码如下:

use std::thread;
use std::sync::mpsc;
use std::time::Duration;fn main() {let (tx,rx) = mpsc::channel();thread::spawn(move || {let vals = vec![String::from("Hello"),String::from("nice"),String::from("to"),String::from("meet"),String::from("you!"),];for val in vals {tx.send(val).unwrap();thread::sleep(Duration::from_secs(1));}});for recv in rx {println!("{}",recv);}println!("Hello, world!");
}

上述代码使用了vec容器,在单个子线程中向主线程发送了多条信息,编译运行结果如下:

root@ThinkPad-T540p:~/learn_rust/learn_thread_channel3# cargo runFinished dev [unoptimized + debuginfo] target(s) in 0.06sRunning `target/debug/learn_thread_channel3`
Hello
nice
to
meet
you!
Hello, world!

同样的,再实现多个线程的情况,代码如下:

use std::thread;
use std::sync::mpsc;
use std::time::Duration;fn main() {let (tx, rx) = mpsc::channel();let tx1 = mpsc::Sender::clone(&tx);let tx2 = mpsc::Sender::clone(&tx);thread::spawn(move || {let vals = vec![String::from("1"),String::from("2"),String::from("3"),String::from("4"),];for val in vals {tx.send(val).unwrap();thread::sleep(Duration::from_secs(1));}});thread::spawn(move || {let vals = vec![String::from("a"),String::from("b"),String::from("c"),String::from("d"),];for val in vals {tx1.send(val).unwrap();thread::sleep(Duration::from_secs(1));}});thread::spawn(move || {let vals = vec![String::from("A"),String::from("B"),String::from("C"),String::from("D"),];for val in vals {tx2.send(val).unwrap();thread::sleep(Duration::from_secs(1));}});for recv in rx {println!("{}",recv);}println!("Hello, world!");
}

编译运行结果如下:

root@ThinkPad-T540p:~/learn_rust/learn_thread_channel4# cargo runCompiling learn_thread_channel4 v0.1.0 (/root/learn_rust/learn_thread_channel4)Finished dev [unoptimized + debuginfo] target(s) in 1.74sRunning `target/debug/learn_thread_channel4`
1
a
A
b
2
B
3
c
C
d
4
D
Hello, world!

可以观察到多个线程发送的信息依次被主线程接收。


总结

以上就是我对通道学习的全过程,最近写了一个线程间循环通信回复的小例子,待完善后会补充到文中以供学习参考。还请各位读者不吝赐教,批评指正。

Rust学习记录 -> 线程之间的通道通信相关推荐

  1. linux 进程和线程或线程和线程之间通过管道通信(pipe)

    linux 进程和线程或线程和线程之间通过管道通信(pipe) 转自:http://blog.csdn.net/robertkun/article/details/8095331 线程间通信: [cp ...

  2. SV学习笔记—线程之间的通信(事件event、信箱mailbox、旗语semaphore)

    目录 0.前言 1.事件event 2.信箱mailbox 3.旗语semaphore 0.前言 若多个线程之间想要进行数据交换或者知道彼此的状态以决定执行什么线程,SV中通过event.mailbo ...

  3. ESP32学习记录<三>串口通信

    ESP32学习记录<三>串口通信 文章目录 ESP32学习记录<三>串口通信 前言 一.通过串口打印出数据 1.初始化串口 2.打印数据 二.串口控制LED亮灭 1.接收串口发 ...

  4. Rust学习记录 -> 关于Crates.io的问题

    文章目录 前言 问题描述与解析 1.版本更迭带来的依赖包适配问题 2. openssl 总结 前言 最近我在使用rust语言编写一个商场后端demo时,由于需要与mysql进行交互以及序列化等操作,所 ...

  5. boost库中mutex、condition_variable与mutex::scoped_lock联合使用实现线程之间的通信

    最近在公司负责一个线程池的模块,里面用到了boost库中的mutex.condition_variable与mutex::scoped_lock,在此总结下线程池在使用时的方式和要点,这里记录了线程之 ...

  6. libevent c++高并发网络编程_高并发编程学习(2)——线程通信详解

    前序文章 高并发编程学习(1)--并发基础 - https://www.wmyskxz.com/2019/11/26/gao-bing-fa-bian-cheng-xue-xi-1-bing-fa-j ...

  7. 高并发编程学习(2)——线程通信详解

    前序文章 高并发编程学习(1)--并发基础 - https://www.wmyskxz.com/2019/11/26/gao-bing-fa-bian-cheng-xue-xi-1-bing-fa-j ...

  8. 多线程学习二之线程之间实现同步

    上篇博客回顾: 1.线程与进程区别:进程是所有线程的集合,线程是进程中的一条执行路径 2.为什么要使用多线程:提高程序效率 3.多线程应用场景:提高程序运行效率,比如迅雷 分批处理数据 4.多线程创建 ...

  9. Java学习笔记——线程

    线程 – 线程的基本概念 程序 :是为完成特定任务.用某种语言编写的一组指令的集合.即指一段静态的代码,静态对象. 进程 :是程序的一次执行过程,或是正在运行的一个程序.是一个动态的过程:有它自身的产 ...

最新文章

  1. 【Linux】一步一步学Linux——crontab命令(132)
  2. 从赖斯想谈恋爱-------到教育的启迪
  3. Win2D 入门教程 VB 中文版 - 防止内存泄漏
  4. 不使用sizeof,获取变量所占用的字节数
  5. db设计专用excel_独家|自卸车如何实现侧板结构快速设计,减少重复工作?
  6. springcloud 网关_Spring Cloud 系列之 Netflix Zuul 服务网关(二)
  7. OpenJudge NOI 1.7 30:字符环
  8. 用户行为分析笔记(二):系统的整体架构
  9. js判断页面点击事件
  10. LeetCode 459. 重复的子字符串(Repeated Substring Pattern)
  11. 神奇的机器人评课_神奇的机器人教学案
  12. 一个月的java工作总结
  13. 后台管理进程GameMaster
  14. STM32 W5500 MQTT Client 发布订阅及断线重连
  15. python中怎样向字典中添加值_python中向一个字典中加值
  16. ZBrush自定义笔刷
  17. python学习——HTMLParser
  18. 汇编基础练习题1:将AX中的数显示输出。
  19. css背景上能添加文字,如何利用div+css来给背景图片上文字布局
  20. 狼人杀3.0版本(自创)

热门文章

  1. 财务自由,靠“投机”能实现吗?(内含福利)
  2. DAU和MAU的分析
  3. python pyqtgraph绘图库-绘制图形
  4. Tensorflow 优化器(optimizer)
  5. 一些电商英文缩写的解释
  6. 2022暑期杭电第八场
  7. LQR控制器——简单实现与仿真
  8. 自建服务器系列-0元搭建linux服务器(windows笔记本)
  9. 事务的基本特性是什么
  10. P4使用Ubuntu中安装教程