rust异步共享数据

1. 手动共享数据

手动共享数据,一个例子如下:

use std::sync::Arc;
use tokio::sync::Mutex;

#[tokio::main]
async fn main() {
    let db: Vec<u32> = vec![1,2,3,4,5,6,7,8,9,10];
    let arc_db = Arc::new(Mutex::new(db));  // 加锁
    let arc_db2 = arc_db.clone();
    let arc_db3 = arc_db.clone();

    let task_a = tokio::task::spawn(async move {
        let mut db = arc_db.lock().await;  // 获取锁
        db[4] = 50;
        assert_eq!(db[4], 50);             // 校验值
    });
    let task_b = tokio::task::spawn(async move {
        let mut db = arc_db2.lock().await;  // 获取锁
        db[4] = 100;
        assert_eq!(db[4], 100);            // 校验值
    });
    _ = task_a.await.unwrap();
    _ = task_b.await.unwrap();

    println!("{:?}", arc_db3.lock().await);  // 获取锁
}

手写线程间共享数据,需要注意:

  • async move,数据需要move到线程中
  • Arc::new(Mutex::new(db)),用Arc,用引用实现共享,用Mutex实现share保护

2. Channel共享数据

一个例子如下

use tokio::sync::mpsc;

#[tokio::main]
async fn main() {
    let mut db: Vec<u32> = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
    let (tx, mut rx) = mpsc::channel::<u32>(100);  // 创建channel

    let tx1 = tx.clone();  // 拷贝两份arc
    let tx2 = tx.clone();

    let task_a = tokio::task::spawn(async move {
        if let Err(_) = tx1.send(50).await {  // 发送端标准写法
            println!("receiver dropped");
            return;
        }
    });
    let task_b = tokio::task::spawn(async move {
        if let Err(_) = tx2.send(100).await {  // 发送端标准写法
            println!("receiver dropped");
            return;
        }
    });

    let task_c = tokio::task::spawn(async move {
        while let Some(i) = rx.recv().await {  // 接收端标准写法
            println!("got = {}", i);
            db[4] = i;
            println!("{:?}", db);
        }
    });
    _ = task_a.await.unwrap();
    _ = task_b.await.unwrap();
    _ = task_c.await.unwrap();
}

channel共享数据是个比较自然的选择,至少需要1个send线程,一个rev线程

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容