Tokio Watch Channel中克隆接收者与订阅发送者的区别是什么?
Tokio Watch Channel:sender.subscribe() 与 receiver.clone() 的差异
先看你给出的代码场景:
let (sender, mut receiver) = watch::channel(1); let receiver_2 = sender.subscribe(); let receiver_3 = receiver.clone();
二者看似功能相近,但有两个容易忽略的关键差异:
1. 初始接收状态完全不同
每个Watch接收者都会维护自己的「是否已确认最新值」的状态:
- 用
sender.subscribe()创建的receiver_2,是一个全新的接收者,它初始状态是未确认当前最新值。也就是说,你直接调用receiver_2.changed().await会立即返回Ok(()),调用recv()也能直接拿到当前sender持有的最新值(这里就是初始化的1)。 - 而
receiver.clone()出来的receiver_3,会完全继承原receiver的状态。如果原receiver已经调用过recv()或者changed()确认过最新值,那么receiver_3也会处于「已确认」状态,此时调用changed().await会阻塞,直到sender发送新的数值。
举个实际代码例子就能看明白:
let (sender, mut receiver) = watch::channel(1); // 让原receiver确认读取初始值 let _ = receiver.recv().await; let receiver_2 = sender.subscribe(); let receiver_3 = receiver.clone(); // receiver_2的changed()会立即返回,因为它还没确认过初始值 assert!(receiver_2.changed().await.is_ok()); // receiver_3的changed()会阻塞,因为它继承了原receiver的已确认状态 // 如果此时sender.send(2).await.unwrap(),才会触发它返回
2. 创建时的依赖对象不同
sender.subscribe()必须通过发送者对象调用,依赖sender的当前可用性(调用时需要&Sender),但创建完成后,receiver_2的存活和sender是否被drop无关,只要channel内部状态还在(有其他发送者或接收者存活),它就能正常工作。receiver.clone()只需要原接收者对象存在即可调用,和sender完全无关,哪怕sender已经被drop,只要原receiver还活着,就能克隆出可用的新接收者。
内容的提问来源于stack exchange,提问作者Pedro
相关产品推荐
相关产品推荐

