「並列」と「並行」を学ぶ – 同期と非同期

プログラミング
この記事は約5分で読めます。

プログラミングをしていると、「同期処理」や「非同期処理」という言葉に必ずと言っていいほど出会います。

この記事では、それらの言葉について、例を交えながら解説していきます。

この記事が向いている人

  • 「同期」や「非同期」の理解があいまいな人

まずは簡単に確認

同期

タスクが順番に実行され、1つのタスクが完了するまで次のタスクは開始されない方法です。

タスク間の依存関係が明確で、順序通りに進行します。

シンプルで予測可能ですが、待ち時間が発生し効率が低いことがあります。

非同期

タスクが同時に実行され、完了の順序は保証されません。

タスクは独立して進行し、待たずに他の作業を進めることができます。

これは効率が向上し、リアルタイム性を高めることができますが、タスクの管理が複雑になることがあります。

ちょっとわかりづらいので例を見てみましょう。

同期

友人と一緒にハンバーガーを買いに行ったとしましょう。

  1. 列に並ぶ:
    • あなたは友人と一緒に列に並んでいます。
    • 列には他のお客さんもいます。
    • 調理係が8人いますが、注文をし終わったお客さんはカウンターで待ち続けるため注文を先に終わらせることができません。
  2. 注文をする
    • あなたの番になったら、注文を行います。
      • メニューを確認し、欲しいものを決定します。
      • 友人の注文も尋ね、記録します。
      • 料金を支払い、お金を正しく渡します。
      • 支払いが正しく処理されたか確認します。
      • 注文が正確であることを確認します。
    • これが、「ハンバーガーの受け取り」というタスクになります🚩。
  3. ハンバーガーの完成を待つ:
    • ハンバーガーが調理されるのをカウンターの前で待ちます
    • レジ係/料理人とあなたたちは「同期」をします。
  4. ハンバーガーを受け取る:
    • ハンバーガーが完成すると、各レジ係がカウンターに戻り、注文をしたお客さんにハンバーガーを渡します。
    • ハンバーガーの受け取り」というタスクが終了します⏹️。
    • あなたはハンバーガーを受け取り、友人とテーブルに行きます。
  5. 食事:
    • テーブルでハンバーガーを食べます。
    • 「ハンバーガーを食べる」という新しいタスクが始まります🚩。

🚩はスタート⏹はタスクの停止を表しています。

これらを図にするとこのようになります。

このように、同期ではタスクを1つ1つ完了させていきます。

今回の場合、待ち時間が多かったため「生産的な」時間がほとんどありませんでした。

そのため、同期処理は今回のような場合には向かないことがわかります。

非同期

こちらも同様、友人とハンバーガーチェーン店に行ったとしましょう

  1. 列に並ぶ
    • あなたは列に並んでおり、順番を待っています。
    • この間、何も生産的なことはしません。プログラムがアイドル状態にあります。
    • レジ係は、列にいる人々から注文を受け取り、注文内容を記録します。
  2. 注文をする
    • あなたの番になったら、注文を行います。
      • メニューを確認し、欲しいものを決定します。
      • 友人の注文も尋ね、記録します。
      • 料金を支払い、お金を正しく渡します。
      • 支払いが正しく処理されたか確認します。
      • 注文が正確であることを確認します。
    • 注文が終わると、店員から番号札が渡されます。
    • これが、「ハンバーガーの受け取り」というタスクになります🚩。
  3. 待機
    • ハンバーガーが調理されるのを待ちます。
    • この間、レジ係はキッチンの男性に注文内容を伝えます。
    • このプロセス、「ハンバーガーの受け取り」は一時停止しています⏸🔀。
  4. テーブルで会話
    • ハンバーガーの準備中、友人とテーブルに座って会話します。
    • これが、「友人との会話」というプロセスになります🚩。
  5. 注文準備完了
    • ハンバーガーの準備が完了すると、レジ係は番号を表示します。
    • 友人との会話」の終了、「ハンバーガーの受け取り」に再び切り替わります🔀。
  6. ハンバーガーを取得
    • カウンターに向かい、ハンバーガーを受け取ります。
    • これで、「ハンバーガーの受け取り」のタスクが完了します⏹。
  7. ハンバーガーを食べる
    • ハンバーガーを食べ、楽しい時間を過ごします。
    • このプロセスは新しいタスクとして開始されます🚩。

🚩はスタート⏸は一時停止🔀は実行するタスクの変化⏹はタスクの停止を表しています。

また、上記の例を図にしてみるとこんな感じです。

途中で2列になっています。

このように、何かをしている途中にほかの処理ができるのが非同期です。

ただ、何も制御しないと注文が出来上がる前に取りに行ってしまうかもしれません。

そのため、非同期処理には、今回の例の「番号札」のような「完了を通知するもの」が必要だといえます。

つまり…?

並列処理(同期処理)は待ち時間が少ない場合

並行処理(非同期処理)は待ち時間が多い場合に有用といえるでしょう。

例えば、今回の同期処理の例では調理人が8人いましたが、待ち時間が多かったため、結局は調理人1人の場合と変わりありませんでした。

しかし、大きい家を掃除する場合ならどうでしょう?

同期処理では、各タスクが順番に実行され、リソース(ここでは清掃員👨‍🍳)が最適に割り当てられます。

これにより、リソースの無駄な待ち時間がなく、全体的な効率が向上します。

待ち時間」という観点から適切に使い分けることが重要ですね。

おわりに

いかがでしたでしょうか?

今回は「同期処理」と「非同期処理」について解説しました。

文面を見ただけではわからないことも、現実であり得る例にあてはめることで理解しやすくなります。

今後は、「同期」「非同期」の入ったプログラムも書いていきたいですねー。

それではまた次回!

参考にさせていただいた記事

並行処理と async / await - FastAPI
FastAPI framework, high performance, easy to learn, fast to code, ready for production

コメント

タイトルとURLをコピーしました