ブロッキングとノンブロッキングとは?

ブロッキングとノンブロッキングは、処理の進み方を表す言葉です。
ブロッキングとは、ある処理が終わるまで次の処理が止まることを意味します。一方、ノンブロッキングでは、時間のかかる処理の完了を待たずに、次の処理を進めることができます。
JavaScriptでは、ファイルの読み込み、通信、タイマー処理などでこの考え方が重要になります。特にブラウザでは、重い処理で画面が固まらないように、非同期処理を使ってノンブロッキングな書き方をすることがよくあります。
ブロッキングの仕組み
ブロッキング処理では、ある処理が終わるまで次の命令は実行されません。
コードの流れが上から順番に進むため理解しやすい一方で、時間のかかる処理があると、その間は他の処理も待たされてしまいます。
ブロッキング処理の例
// Node.jsでの例
const fs = require("fs");
const data = fs.readFileSync("sample.txt", "utf8");
console.log(data);
console.log("ファイル読み込み後に実行される処理");
この例では、readFileSync()でファイルの読み込みが完了するまで、次のconsole.log()は実行されません。
readFileSync()は同期的にファイルを読み込みます。- ファイルの読み込みが終わるまで、次の処理は待機します。
- 処理の流れは分かりやすいですが、時間がかかる処理では注意が必要です。
ノンブロッキングの仕組み
ノンブロッキング処理では、時間のかかる処理の完了を待たずに次の処理が進みます。
JavaScriptでは、コールバック関数、Promise、async/awaitなどを使って非同期処理を行います。これにより、通信やファイル読み込みの完了を待っている間も、他の処理を進められます。
ノンブロッキング処理の例
// Node.jsでの例
const fs = require("fs");
fs.readFile("sample.txt", "utf8", (err, data) => {
if (err) {
console.error(err);
return;
}
console.log(data);
});
console.log("ファイル読み込み中でも実行される処理");
この例では、readFile()が非同期でファイルを読み込みます。そのため、ファイルの読み込みが終わる前に、次のconsole.log()が実行されます。
readFile()は非同期処理です。- ファイルの読み込み完了を待たずに、次の処理へ進みます。
- 読み込みが終わった後、コールバック関数の中の処理が実行されます。
ブロッキングとノンブロッキングの比較
ブロッキング処理とノンブロッキング処理の違いを整理すると、次のようになります。
| 種類 | 特徴 | 向いている場面 |
|---|---|---|
| ブロッキング処理 | 処理が終わるまで次の処理が止まる。 | 短く単純な処理、順番に実行したい処理 |
| ノンブロッキング処理 | 処理の完了を待たずに次の処理へ進む。 | 通信、ファイル読み込み、タイマー処理など |
JavaScriptでは、時間のかかる処理ではノンブロッキングな書き方がよく使われます。
ブロッキングが問題となるケース
ブロッキング処理は、処理が短ければ大きな問題になりません。しかし、処理に時間がかかると、ブラウザの画面が固まったように見えることがあります。
ブロッキング処理によるフリーズの例
function waitForLongTask() {
const start = Date.now();
while (Date.now() - start < 5000) {
// 5秒間、何もしないで待つ
}
console.log("長時間の処理が完了しました");
}
waitForLongTask();
console.log("次の処理が実行される");
この例では、while文で5秒間処理を止めています。その間、次の処理は実行されません。
whileの処理が終わるまでJavaScriptの実行が止まります。- ブラウザでは、その間画面操作が重くなったり、固まったように見えたりします。
- 長時間かかる処理は、できるだけ非同期処理として扱うことが重要です。
ノンブロッキング処理の利点
ノンブロッキング処理には、次のような利点があります。
- 時間のかかる処理を待っている間も、他の処理を進められる。
- ブラウザの画面が固まりにくくなる。
- API通信やファイル読み込みを効率よく扱える。
- ユーザー操作に対してスムーズに反応しやすくなる。
特にWebアプリケーションでは、ユーザーが操作している間に通信や読み込みを行うことが多いため、ノンブロッキング処理の理解は重要です。
async/awaitを使ったノンブロッキング処理
現在のJavaScriptでは、Promiseを扱いやすくするためにasync/awaitがよく使われます。
async/awaitの例
async function fetchData() {
const response = await fetch("https://example.com/data.json");
const data = await response.json();
console.log(data);
}
fetchData();
console.log("データ取得中にも他の処理が進む");
awaitを使うと、非同期処理を上から順番に書いているように見せることができます。ただし、関数全体が完全にブロッキングになるわけではありません。
fetchData()は非同期関数です。awaitは、その非同期関数の中で結果を待ちます。fetchData()の外側にあるconsole.log()は、データ取得を待たずに実行されます。
ブロッキングと同期処理、ノンブロッキングと非同期処理
初心者のうちは、次のように考えると分かりやすいです。
| 用語 | 意味 |
|---|---|
| 同期処理 | 上から順番に処理を実行する書き方。 |
| 非同期処理 | 時間のかかる処理の完了を待たずに、次の処理へ進める書き方。 |
| ブロッキング | 処理が終わるまで次の処理が止まる状態。 |
| ノンブロッキング | 処理の完了を待たずに次の処理を進められる状態。 |
厳密にはすべて同じ意味ではありませんが、JavaScriptの学習初期では「同期処理は待つ」「非同期処理は待たずに進む」と考えると理解しやすくなります。
まとめ
- ブロッキングとは、ある処理が終わるまで次の処理が止まることです。
- ノンブロッキングとは、処理の完了を待たずに次の処理へ進めることです。
- JavaScriptでは、非同期処理を使ってノンブロッキングな処理を実現します。
- ファイル読み込みやAPI通信など、時間のかかる処理ではノンブロッキングが重要です。
- ブラウザで重い同期処理を行うと、画面が固まったように見えることがあります。
async/awaitを使うと、非同期処理を読みやすく記述できます。- ブロッキングとノンブロッキングを理解すると、JavaScriptの非同期処理を学びやすくなります。