34|并发处理(下):从atomics到Channel,Rust都提供了什么工具?
陈天
该思维导图由 AI 生成,仅供参考
你好,我是陈天。
对于并发状态下这三种常见的工作模式:自由竞争模式、map/reduce 模式、DAG 模式,我们的难点是如何在这些并发的任务中进行同步。atomic / Mutex 解决了自由竞争模式下并发任务的同步问题,也能够很好地解决 map/reduce 模式下的同步问题,因为此时同步只发生在 map 和 reduce 两个阶段。
然而,它们没有解决一个更高层次的问题,也就是 DAG 模式:如果这种访问需要按照一定顺序进行或者前后有依赖关系,该怎么做?
这个问题的典型场景是生产者 - 消费者模式:生产者生产出来内容后,需要有机制通知消费者可以消费。比如 socket 上有数据了,通知处理线程来处理数据,处理完成之后,再通知 socket 收发的线程发送数据。
Condvar
所以,操作系统还提供了 Condvar。Condvar 有两种状态:
等待(wait):线程在队列中等待,直到满足某个条件。
通知(notify):当 condvar 的条件满足时,当前线程通知其他等待的线程可以被唤醒。通知可以是单个通知,也可以是多个通知,甚至广播(通知所有人)。
在实践中,Condvar 往往和 Mutex 一起使用:Mutex 用于保证条件在读写时互斥,Condvar 用于控制线程的等待和唤醒。我们来看一个例子:
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
- 深入了解
- 翻译
- 解释
- 总结
Rust提供了丰富的并发处理工具,包括atomics、Mutex、Condvar和各种类型的Channel,以及Actor模型的实现。这些工具可以帮助开发者处理并发任务之间的通讯和同步,实现“无畏并发”。文章介绍了这些工具的使用场景和特点,以及如何利用它们解决不同的并发问题。通过示例代码展示了如何使用Condvar实现线程间通信和同步,以及利用Channel处理复杂的DAG并发模式。此外,文章还强调了Rust提供的多样化并发原语的重要性,以及在实际应用中灵活选择合适的工具的必要性。总体而言,Rust为开发者提供了丰富的并发处理工具,使并发编程变得更加简单和灵活。
仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《陈天 · Rust 编程第一课》,新⼈⾸单¥68
《陈天 · Rust 编程第一课》,新⼈⾸单¥68
立即购买
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
登录 后留言
全部留言(14)
- 最新
- 精选
- ×22请问一下,目前rust的标准库中并没有类似concurrent hash map等并发安全的集合,虽然第三方库有一些实现,但是不容易从中做出选择,请问老师有什么推荐吗
作者回复: dashmap,如果你的使用场景适合的话,也可以尝试 Jon 写的 left-right: https://github.com/jonhoo/left-right
2021-12-173 - 核桃Channel 把锁封装在了队列写入和读取的小块区域内,然后把读者和写者完全分离,使得读者读取数据和写者写入数据,对开发者而言,除了潜在的上下文切换外,完全和锁无关,就像访问一个本地队列一样 这段文字,我还是没有很明白,所谓对于channel和mutex锁的区别,是不是可以这样理解?channel可以看成是一个队列(vec那样的),然后channel这里就是一头写入一头消费,那么如果有并发的时候,就是对头尾进行加锁,并且会做多一些其他的辅助操作,例如队列满了或者空的时候各种安全检查判断等等,实际上channel就是对mutex+queue的抽象封装? 多谢了
作者回复: 对,高级的并发原语都是低级的原语的组合和做了精心的使用限制。我文中有讲到什么样的 channel 大概用了什么样的技术去实现。比如 mpsc,因为 consumer 只有一个,所以实现地好的话 consumer 侧不需要锁。
2021-12-052 - newzaigo经常会使用 chan struct 来作为actor对象的退出信号,rust有什么建议不?不想和数据channel混合在一起。
作者回复: 你可以使用单独的 channel,也可以用 condvar,也可以用第三方封装好的 signal。
2021-11-161 - 千回百转无劫山读完本节有一个感悟,actor model是异步任务级别的“微服务”:发送信息给一个actor,然后从actor再接收信息,就类似于后端中发送一个请求给一个微服务,再接收响应。也就是说,一个actor对应一个“”微服务“”,不知道这种理解是否正确?还有就是,一个actor对应的是类似于tokio的一个task吗?
作者回复: 理解正确
2021-11-16 - 罗杰对,合理的使用 Channel,不应该死搬硬套。
作者回复: 👍
2021-11-15 - GengTeng笨拙地用 Channel 叠加 Channel 来应对所有的场景?Go: 你直接说我名儿得了。
作者回复: 哈哈
2021-11-152 - 朱叶子工作线程中,缺了drop(started),导致主线程无法获取mutex2022-06-244
- Geek_e188ed老师,代码示例有点少啊,比如Channel这块,你的文字描述我都看懂了,但是没有使用Channel的代码示例,可能怎么调用我都不知道2022-07-1012
- 终生恻隐#[test] fn test_mpsc() { let (a2btx, a2brx) = mpsc::channel(); let (b2atx, b2arx) = mpsc::channel(); let threada = thread::spawn(move || { a2btx.send("hello world!".to_string()).unwrap(); for re in b2arx { println!("{}\n", re); thread::sleep(Duration::from_secs(1)); a2btx.send("hello world!".to_string()).unwrap(); } }); let threadb = thread::spawn(move || { for re in a2brx { println!("{}\n", re); thread::sleep(Duration::from_secs(1)); b2atx.send("goodbye!".to_string()).unwrap(); } }); thread::sleep(Duration::from_secs(10)); return }2021-11-151
- Rex WangMutex使用lock方法生成Guard锁住数据,而Guard通过drop方法才能把数据解锁。老师的例子化用了doc中的例子,但因为没有对变量 started 显式使用drop方法,而使用loop阻塞了 started 自动调用drop,所以和预设的结果表现不同。2023-09-08归属地:北京
收起评论