Rustの非同期性はFutureを通じて実現されており、これは将来得られる結果を表す作業のオブジェクトです。async fnを使用して宣言された関数は、Futureトレイトを実装する無名構造体(ジェネレータ)を返します。非同期コードを実行するにはランタイム(例えば、Tokioやasync-std)を使用する必要があります。標準ライブラリには組み込みのイベントループがありません。
Rustの主な特徴:
例:
use tokio::time::sleep; use std::time::Duration; async fn foo() { println!("Hello"); sleep(Duration::from_secs(1)).await; println!("World!"); } #[tokio::main] async fn main() { foo().await; }
Rustの非同期関数は、呼び出し時にデフォルトで即座に実行されることがありますか?なぜですか?
答え:
いいえ。async fnの呼び出しは結果を返すのではなく、Futureタイプ(状態機械)のオブジェクトを返します。実際の実行には.awaitを呼び出すか、Futureをランタイムに渡す必要があります。呼び出し自体はタスクの説明を作成するだけで、実行はされません。
例:
async fn answer() -> u32 { 42 } let fut = answer(); // ここでは実行されず、futureの作成のみ let result = fut.await; // ここで実行が始まる
物語
.awaitを呼び出しませんでした。そのため、主要なスレッドは同期的に実行され、パフォーマンスの低下と応答時間が3倍に増加しました。物語
物語
チームのメンバーの1人が、Future内で使用される型に対するSend/Syncの制約を忘れました。スレッド間でfutureを共有しようとした際、特定の構造体に対してSendを実装する必要があるというコンパイラエラーが発生し、状態保存のアーキテクチャを見直す必要が生じました。