Rust中tokio::sync::watch的borrow与borrow_and_update区别解惑
区分tokio::sync::watch中borrow()和borrow_and_update()的差异
两者核心差异在于是否更新订阅者的"已查看版本"标记:
- borrow():仅获取当前最新值的不可变引用,不会修改订阅者的版本标记。之前未被标记为已查看的更新,后续调用
changed().await仍会检测到。 - borrow_and_update():获取当前最新值引用的同时,将订阅者的版本标记同步到最新。后续
changed().await会阻塞,直到发送端产生新的更新。
示例1:使用borrow()的行为
#[tokio::main] async fn main() { use tokio::sync::watch; use tokio::time::{Duration, sleep}; let (tx, mut rx) = watch::channel(0); tokio::spawn(async move { // 仅借用值,不更新版本标记 println!("初始值:{}", *rx.borrow()); // 连续发送两次更新 tx.send(1).unwrap(); tx.send(2).unwrap(); // changed()立即返回,因为存在未标记的更新 if rx.changed().await.is_ok() { println!("第一次changed后的值:{}", *rx.borrow()); } // 再次调用changed()仍会立即返回,还有一次未处理的更新 if rx.changed().await.is_ok() { println!("第二次changed后的值:{}", *rx.borrow()); } }); sleep(Duration::from_millis(100)).await; }
运行结果:
初始值:0 第一次changed后的值:2 第二次changed后的值:2
这里borrow()没更新标记,两次send的更新都会被changed()捕获(watch仅保留最新值,旧更新会被覆盖)。
示例2:使用borrow_and_update()的行为
#[tokio::main] async fn main() { use tokio::sync::watch; use tokio::time::{Duration, sleep}; let (tx, mut rx) = watch::channel(0); tokio::spawn(async move { // 借用值的同时更新版本标记到最新 println!("初始值:{}", *rx.borrow_and_update()); // 连续发送两次更新 tx.send(1).unwrap(); tx.send(2).unwrap(); // changed()立即返回,此时标记同步到最新的2 if rx.changed().await.is_ok() { println!("changed后的值:{}", *rx.borrow()); } // 再次调用changed()会阻塞,等待新的更新 println!("等待新的更新..."); match rx.changed().await { Ok(_) => println!("收到新值:{}", *rx.borrow()), Err(_) => println!("发送端已关闭"), } }); sleep(Duration::from_millis(1000)).await; tx.send(3).unwrap(); sleep(Duration::from_millis(100)).await; }
运行结果:
初始值:0 changed后的值:2 等待新的更新... 收到新值:3
这里borrow_and_update()将标记更新到0的版本,两次send后changed()同步到最新的2版本,再次调用changed()会阻塞,直到新值3被发送。
为什么你的原示例看不出区别?
你的代码中同时使用了rx和rx2两个独立的订阅者,rx2的borrow/borrow_and_update操作不会影响rx的版本标记,两个订阅者状态完全独立,操作互不干扰,因此替换方法后rx.changed()的行为没有变化。
内容的提问来源于stack exchange,提问作者Shivam Varshney
相关产品推荐
相关产品推荐

