16|tokio编程:使用channel在不同任务间通信?
唐刚
你好,我是 Mike。今天我们来了解并发编程的另一种范式——使用 channel 在不同的任务间进行通信。
channel 翻译成中文就是通道或管道,用来在 task 之间传递消息。这个概念本身并不难。我们回忆一下上节课的目标:要在多个任务中同时对一个内存数据库进行更新。其实我们也可以用 channel 的思路来解决这个问题。
我们先来分解一下任务。
创建三个子任务,task_a、task_b 和另一个起代理作用的 task_c。
在 task_a 和 task_b 中,不直接操作 db 本身,而是向 task_c 发一个消息。
task_c 里面会拿到 db 的所有权,收到从 task_a 和 task_b 来的消息后,对 db 进行操作。
基于这个思路,我们来重写上一节课的示例。
MPSC Channel
我们使用 tokio 中的 MPSC Channel 来实现。MPSC Channel 是多生产者,单消费者通道(Multi-Producers Single Consumer)。
MPSC 的基本用法如下:
使用 MPSC 模块的 channel() 函数创建一个通道对,tx 表示发送端,rx 表示接收端,rx 前面要加 mut 修饰符,因为 rx 在接收数据的时候使用了可变借用。channel 使用的时候要给一个整数参数,表示这个通道容量多大。tokio 的这个 mpsc::channel 是带背压功能的,也就是说,如果发送端发得太快,接收端来不及消耗导致通道堵塞了的话,这个 channel 会让发送端阻塞等待,直到通道里面的数据包被消耗到留出空位为止。
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
- 深入了解
- 翻译
- 解释
- 总结
本文深入介绍了使用tokio中的channel进行并发编程的方法和技巧。通过使用MPSC Channel(多生产者,单消费者通道)实现了任务间的消息传递,并通过示例代码演示了如何利用代理模式处理消息。此外,文章还介绍了tokio中的其他channel类型,包括broadcast channel和watch channel,以及任务管理的两种常见模式。通过丰富的示例和详细的解释,读者可以快速了解并掌握并发编程的相关知识。文章还提供了思考题,鼓励读者留下自己的思考和疑问,以及分享给其他朋友。整体而言,本文对于想要深入了解并掌握并发编程的读者来说,是一篇非常有价值的文章。
仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《Rust 语言从入门到实战》,新⼈⾸单¥59
《Rust 语言从入门到实战》,新⼈⾸单¥59
立即购买
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
登录 后留言
全部留言(11)
- 最新
- 精选
- Aaaaaaaaaaayoujoin 和 select 类似于 JavaScript 中的 Promise.all 和 Promise.race
作者回复: 👍
2024-01-26归属地:广东1 - 刘丹请问老师: r = task_a => r.unwrap() 这是闭包,还是匿名函数?
作者回复: 这是tokio那个宏里面的特殊语法,不是标准的rust语法。就是一个语法而已。既不是闭包,也不是匿名函数
2023-11-24归属地:广东1 - superggn背压 - back pressure 带背压的 channel tokio::mpsc::channel(n) std::mpsc::sync_channel(n) 不带背压的 channel tokio::mpsc::unbounded_channel(); std::mpsc::channel();
作者回复: 👍
2024-01-26归属地:北京 - superggn思考题 - Arc::new(Mutex::new(target_var)); - res = join_handler.await.unwrap(); - channel
作者回复: 棒棒哒
2023-12-25归属地:北京 - superggn捉虫: `等待所有任务一起返回` main 前面少个 fn
作者回复: 哈哈,感谢指出,可能编辑的时候漏了。尽快处理
2023-12-25归属地:北京 - 刘永臣.await()类似于等待组吧? channel的四种模式也是go channel常用的四种场景。
作者回复: await是单个任务。rust中waitgroup实现也很简单。四种模式对应起来了,可能tokio就是借鉴的go channel。
2023-11-28归属地:北京 - 学水如果通道都没有任何生产者消息,select语句中的消费者是堵塞在那里还是会之间进入下一个语句呢
作者回复: rx.await就是在task层面阻塞住。
2023-11-25归属地:加拿大 - 老大为啥我按照你写的,运行不起来呢?
作者回复: 你可以帖一下代码。
2023-11-24归属地:河南 - PEtFiSh从任务收集返回结果的方式有: 1、任务直接返回值,然后通过handler取回,比如:a = task_a.await.unwrap(); 2、通过锁的方式直接写在目标位置 3、通过channel的形式传递结果 4、似乎也可以unsafe来写全局变量。
作者回复: 👍,很棒。mpsc 和 oneshot 都可以派上用场。
2023-11-24归属地:上海 - 伯阳这种无锁并发,快是快了点,但是如果给通道打满了,怎么处理呢
作者回复: 打满了就阻塞了。打不进去了,就等吧,消耗一个就能打进去一个。
2023-11-24归属地:北京
收起评论