コンテンツにスキップ

【比較】同期・非同期の違い

概要

同期処理と非同期処理の最大の違いは、処理の完了を「待つか、待たないか」です。同期(synchronous)は一つの処理が完全に終わるまで次に進まずブロックする方式、非同期(asynchronous)は完了を待たずに次へ進み、結果は後からコールバック・Promise・イベントなどで受け取るノンブロッキングな方式です。

なお、同期・非同期は「シングルスレッドかマルチスレッドか」とは別の軸(直交する概念)です。たとえば JavaScript はシングルスレッドのままイベントループで非同期処理を実現します。本記事では言語ランタイムの公式な定義に沿って整理します。

詳細比較

項目 同期処理 (Synchronous) 非同期処理 (Asynchronous)
実行順序 厳密な順番で一つずつ実行 完了を待たずに次の処理を開始
処理の待ち時間 処理が終わるまで待つ (ブロックする) 処理を待たずに進める (ノンブロッキング)
効率性 一つの処理が遅いと全体が遅くなる 時間のかかる処理を効率化できる
プログラムの複雑さ 単純で分かりやすい 複雑になりやすい
適した用途 順序が重要な単純なタスク ネットワーク通信やファイル操作など、待ち時間が発生する処理

同期 (Synchronous)

一つの処理が完全に終了するまで、次の処理を開始せずに待機する方式です。

  • 特徴:
    • 処理が順番に一つずつ実行される。
    • 上から下に書かれたコードが、書かれた通りの順序で完了していく。
  • 身近な例:
    • スーパーのレジ: 前の人の会計が完全に終わらないと、自分の会計は始まりません。一つのタスクが終わるまで、次のタスクは待機します。
  • 利点:
    • 処理の流れが直線的で分かりやすい。
  • 欠点:
    • 一つの処理に時間がかかると、その間すべての処理が停止してしまう(ブロッキング)。

非同期 (Asynchronous)

一つの処理の完了を待たずに、次の処理を開始できる方式です。先に始めた処理が後から完了することもあります。

  • 特徴:
    • 時間のかかる処理(例: ファイルの読み込み、サーバーとの通信)を待っている間に、他の処理を進められる。
    • 結果はコールバック・Promise・イベント(イベントループ)などで後から受け取る。
  • 身近な例:
    • レストランの呼び出しベル: 料理を注文した後、席で待っている間に他のことができます(例: 友人と話す)。料理ができたらベルが鳴って知らせてくれます。注文(タスク)の完了を待たずに、他のことができます。
  • 利点:
    • 時間のかかる処理があっても、他の処理を止めないため、システムの応答性が向上する。
    • 待ち時間(I/O 待ちなど)を有効活用でき、全体のスループットが上がる。
  • 欠点:
    • 処理の完了順序が保証されないため、プログラムの構造が複雑になりやすい。

よくある誤解

  • 「非同期 = マルチスレッド(並列)」は誤り。 同期/非同期は「呼び出し元が完了を待つかどうか」、シングル/マルチスレッドは「実行の担い手が1つか複数か」という別の軸です。MDN が明示するとおり JavaScript はシングルスレッドのままイベントループで非同期を実現します。非同期だからといって、複数の処理が物理的に同時実行されているとは限りません(※「並行と並列の違い」も参照)。

  • 「非同期にすれば必ず速くなる」は誤り。 非同期が効くのは主に I/O 待ちなど「待ち時間がある処理」です。待ち時間に他の仕事を進められるためスループットや応答性が上がりますが、CPU を使い切る計算自体が速くなるわけではありません。CPU バウンドな処理の高速化には並列実行が必要です。

  • 「非同期では処理の完了順序が書いた順になる」は誤り。 非同期では先に開始した処理が後から完了し得ます。順序に依存するロジックは Promise チェーン/await/イベントの順序制御で明示的に担保する必要があり、これが「複雑になりやすい」と言われる主因です。

実務での選び分け

  • 順序が重要で処理が短い/結果をその場で使う → 同期。コードが直線的で読みやすく、デバッグも容易。
  • ネットワーク通信・ファイル/DB アクセスなど待ち時間が支配的 → 非同期(async/await、Promise、イベントループ)。待ち時間に他のリクエストを処理でき、応答性とスループットが向上する。
  • CPU バウンドな重い計算を速くしたい → 非同期だけでは不十分。並列実行(マルチプロセス/ワーカースレッド/GPU)を併用する。
  • 複雑な非同期フローを書くとき → コールバックの入れ子を避け、Promise / async-await や構造化並行性で順序と例外を明示的に扱う。

ひとことまとめ

同期は「処理の完了を待ってから次へ進む(ブロッキング)」、非同期は「完了を待たず次へ進み結果は後で受け取る(ノンブロッキング)」方式であり、これはスレッド数(シングル/マルチ)とは独立した別の軸です。

出典・参考