JavaScript 同期処理・非同期処理について
はじめに
スレッド・メインスレッドについて
スレッドとは、プログラムの開始から終了までの一連の流れのこと。
ブラウザ上で、JavaScriptのコードが実行されるスレッドは、メインスレッド。
メインスレッドは、1つのスレッド。並列したコードは実行できない。
同期処理と非同期処理の基本的な違いについて
- 実行順序
同期処理では処理が順番に行われ、非同期処理では複数の処理が並列に行われる。 - ブロッキングの有無
同期処理は処理中のタスクが終わるまで次のタスクに移れない(ブロッキング)、非同期処理はタスクの完了を待たずに次のタスクに移る(ノンブロッキング)。 - 処理の効率
同期処理はシンプルで理解しやすいが、タスクの処理時間が全体の処理時間に直接影響する。非同期処理は複雑さが増すが、効率的にタスクを管理できる。
同期処理とは
メインスレッド上で、1行ずつ順番に実行される処理。
1つのスレッドで、前の処理の完了を待ってから次の処理を実行する。
この方式では、あるタスクの処理がブロック(停止)すると、全体の処理がそのタスクが完了するまで待つ必要がある。
非同期処理とは
非同期処理は、メインスレッドで実行される処理から一時的に「切り離された」タスクを指す。
非同期処理の特徴は、
- 処理が完了するのを待たずに、次の処理が実行される
これにより長時間実行される処理や外部リソースへのアクセスが他の処理の実行をブロックしないようにする。
例え
A→B→Cの処理があります。
Bが非同期処理の場合
- Aの実行: メインスレッドでAの処理が実行されます。
- Bの非同期実行: Bの処理が開始されますが、これはメインスレッドから「切り離され」、非同期で実行されます。具体的には、Bの処理はメインスレッドの実行フローとは独立してバックグラウンドで処理され、Bの完了をメインスレッドが待つことはありません。
- Cの実行: Bの処理が完了するのを待たずに、メインスレッドはCの処理に進みます。
- Bの完了: Bの非同期処理がいずれ完了すると、その結果はメインスレッドで処理されるか、コールバック関数、Promiseの解決、async/awaitなどを通じて取り扱われます。
console.log('Aの処理を開始します。');
// Bの処理(非同期処理)
setTimeout(() => {
console.log('Bの処理(非同期処理)が完了しました。');
}, 2000); // 2000ミリ秒(2秒)後に実行
console.log('Cの処理を開始します。');
実行結果
Aの処理を開始します。
Cの処理を開始します。
Bの処理(非同期処理)が完了しました。
同期・非同期処理の実世界の例
-
「レストランでの注文」の例え話を使って同期処理
あなたがレストランに行って、注文します。
あなたが、店員さんにコーヒーを頼みました。
店員さんは、コーヒーを用意してから次のお客さんの注文を取りに行くという方法で
働いています。
この場合、店員さんはあなたのコーヒーが用意できるまで、他の仕事は一切できません。
このプロセスが同期処理に似ています。
一つのタスクが完了するまで次のタスクには移れず、処理がブロックされます。 -
「レストランでの注文」の例え話を使って非同期処理
今度は、あなたがコーヒーを注文した後、店員さんはキッチンにその注文を伝え、
コーヒーが用意されるのを待つ間に他のテーブルの注文を取りに行ったり、
別のお客さんに食事を運んだりします。
コーヒーが用意できたら、店員さんはあなたのテーブルにそれを届けます。
このプロセスが非同期処理に似ています。
店員さん(メインスレッド)は、コーヒーが用意される(時間のかかるタスクが完了する)のを待つ間に、他のタスクを続けることができます。
コーヒーが用意できたら(非同期タスクが完了したら)、それに応じた処理(コールバック)が行われます。
まとめ
今回は、JavaScriptの同期・非同期処理にまとめていきました。
私自身、普段からasync
・await
など非同期処理を使用していますが、
メインスレッドなどのことなどは意識していませんでした。
実例を交えることによって、少しずつ理解できました。
次は、Promise
とasync
・await
の違いについて調べたいです。
Discussion