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线程