Я обнаружил, что этот пример компилируется успешно, но не является ли поток Rc<> небезопасным? Что, если tikio запустит многопоточность для выполнения теста fn, не приведет ли это к тому, что Rc будет работать в разных потоках?
use std::rc::Rc;
use tokio::join;
use std::time;
use async_std::task::{sleep};
async fn test(t:Rc<String>){
let k = t;
println!("1. test,{:?}", k);
sleep(time::Duration::from_secs(1)).await;
println!("2. test,{:?}", k);
}
#[tokio::main]
async fn main() {
let r = Rc::new("abc".to_string());
let f1 = test(r.clone());
let f2 = test(r.clone());
join!(f1,f2);
}
Это немного нюанс, но #[tokio::main]
перепишет ваш async main()
примерно так:
fn main() {
tokio::runtime::Builder::new_multi_thread()
.enable_all()
.build()
.unwrap()
.block_on(async {
// your code from `async main()`
})
}
Последний шаг, который фактически запускает все, .block_on(), не требует, чтобы данная задача была потокобезопасной (также известной как реализация Send
), потому что она не будет выполняться в отдельном потоке, даже при использовании многопоточной исполнитель:
Это запускает данное будущее в текущем потоке, блокируя его до тех пор, пока оно не будет завершено, и давая разрешенный результат.
Другие утилиты tokio и любые порожденные задачи могут выполняться в отдельных потоках и даже перемещаться между ними, но не исходная задача.
Согласно документации, «в результате компилятор Rust будет проверять во время компиляции, что вы не отправляете Rcs между потоками». Если этот код компилируется, кажется, что вы не «отправляете Rcs между потоками», и этот код безопасен для памяти. Я не уверен в этом на 100%, я просто опираюсь на документы, а вы говорите, что этот код компилируется.