プログラムを動かすとき、「この処理が終わるまで待たなきゃいけないのかな」って思ったことありませんか?スマートフォンのアプリとか、パソコンでファイルを保存するとき、処理の順序って結構大事なんです。実は、コンピュータが仕事をする方法には大きく分けて2種類あって、その1つが「同期処理」なんです。この記事を読めば、「あ、だからこんなふうに動いてるんだ」って理解できるようになりますよ。
- 同期処理とは、1つの処理が終わるまで次の処理に進まない処理方式のことだ。
- 料理や銀行の窓口のように、順番待ちが発生するのが特徴で、確実だけど時間がかかることがある。
- プログラムの動きを安定させるために、同期処理はとても重要な役割を果たしているんだ。
もうちょっと詳しく
同期処理っていうのは、実はプログラミング言語の基本的な考え方なんだ。パソコンが命令を実行するとき、「1行目を実行して、1行目が完全に終わったら2行目を実行する」っていう流れになっているんだよ。これをコンピュータ科学では「制御フロー」(つまり、処理の流れがどう動くか)って言うんだけど、同期処理はこの流れがシンプルでわかりやすいんだ。だから初心者でも理解しやすいし、バグが少なくなりやすいんだよ。プログラムが予期しない動作をしたときに「何が起きたのか」が追いやすいんだ。
同期処理は「理解しやすい」「安全」という利点があるから、基本的にはこっちを使うんだよ。
⚠️ よくある勘違い
→ 遅い、速いというのは処理の内容で決まるんであって、同期か非同期かじゃないんだ。同期処理でも物すごく速い処理もあるし、遅い処理もあるんだよ。
→ 同期処理とは「待つ」という考え方で、速度は「何の処理をするか」で決まるんだ。この2つは独立した考え方なんだよ。
[toc]
同期処理とは何か
同期処理について説明する前に、まず「処理」って何かを考えてみようね。コンピュータの世界では、「処理」というのは「やることのリスト」みたいなものなんだ。例えば、スマートフォンで写真を撮るとき、こんなことが起きているんだよ:
- カメラを起動する
- ピントを合わせる
- シャッターボタンを押す
- 写真のデータをメモリに保存する
- 画面に保存完了メッセージを表示する
この5つのステップを、まさにこの順番で、1つ前の作業が完全に終わるまで次には進まない。これが「同期処理」なんだ。つまり、同期処理とは「1つの処理が終わるまで、次の処理が始まらない」という決め方のことなんだよ。
では、なぜこんなやり方があるのか。それはね、コンピュータの中にはいろんな部品があって、それらが互いに協力して仕事をしているからなんだ。例えば、写真を保存する前に、まずメモリが「保存できるか」を確認しなくちゃいけないんだよ。準備ができていない状態で保存しようとしたら、データが壊れちゃうかもしれない。だから「待つ」ってことが大事なんだ。
実生活で例えるなら、図書館で本を借りるときのことを考えてみて。カウンターに並んでいる人たちは、その順番に1人ずつ借りるんだよね。Aさんが1番前に並んでいたら、Aさんの手続きが完全に終わるまで、後ろの人は前に進むことができない。これが同期処理だ。順番が守られて、秩序が保たれるんだよ。
同期処理の基本ルール
同期処理には、いくつかの基本的なルールがあるんだ。1つ目は「順番が決まっている」ってことだ。A→B→C という順序で実行されるんだよ。2つ目は「待つ時間がある」ってこと。Aが終わるまで、Bは絶対に始まらない。これが重要なんだ。3つ目は「結果が予測しやすい」ってこと。順番が決まっているから、何が起きるかわかりやすいんだ。最後に4つ目は「エラー対応が簡単」ってことだね。「ここでエラーが起きたな」ってすぐわかるんだよ。この4つが揃っているのが同期処理なんだ。だから初心者がプログラムを書くときは、ほぼ同期処理のやり方で書くんだ。複雑なことを考えなくていいから、集中できるんだよ。
日常生活での同期処理の例
ね、同期処理って実は私たちの生活の中でいっぱい見かけるんだよ。知らないうちに、いろんなとこで使われているんだ。
「レジでの精算」がいい例だね。スーパーマーケットのレジに並んでいる人たちを考えてみて。1番目の人が商品をスキャンしてもらって、支払いをして、買い袋に詰めて…やっと退場する。その後で、初めて2番目の人の番になるんだよ。1番目の人の処理が完全に終わるまで、2番目の人は動けない。これが同期処理だ。もし2番目の人が1番目の人より先に支払っちゃったら?混乱しちゃうでしょ。同期処理なら、こういう心配がないんだよ。
「料理の手順」も同期処理の例だね。カレーを作るとき、タマネギを切って、次に炒める。加熱時間は5分だ。その間に別のことをしたり、タマネギを炒める前に次のニンジンを加えたりはしないんだよ。1番目のステップが終わらないと、2番目に進めないんだ。まだタマネギを切っている途中に、いきなり炒められないでしょ。このように、料理って本質的には同期処理で構成されているんだ。食べ物だからこそ、順番をきっちり守らなくちゃダメなんだよ。
「映画館での映写」もそうだね。映画は1フレーム目が表示されて、その次に2フレーム目が表示される。その順番は絶対に逆転しないんだ。もし、10フレーム目が1フレーム目より先に表示されたら、映画は成り立たないんだよ。1秒間に30フレームが順番に表示されるから、我々には「動いてる」ように見えるんだ。
「銀行での振込」も同期処理だ。振込手数料を引いて、口座番号を確認して、相手の口座に送金して、取引記録を保存する。この全部が順番に行われるんだよ。途中で「あ、手数料はいくら?」なんて計算してたら、送金できないんだ。お金の移動だからこそ、絶対に同期処理で守られなきゃいけないんだよ。
このように、日常生活ではあちこちで同期処理が使われているんだ。私たちは「順番を守る」ってことが大事だって、無意識に理解しているんだ。
プログラミングでの同期処理
さて、ここからが本論だね。プログラミングの世界では、同期処理はどんなふうに使われているのか。
プログラミング言語(つまり、コンピュータに命令する言葉)で書かれたコードは、基本的に上から下へ、順番に実行されるんだ。例えば、Pythonという言語で書くとしたら、1行目に「x = 5」と書いたら、まずこの命令が実行される。次に2行目の「y = 10」が実行される。その次に「z = x + y」で計算が起きて、最後に「print(z)」で画面に結果が表示されるんだ。コンピュータは「4番目の表示」をする前に、必ず「3番目の計算」が終わるまで待つんだよ。これが同期処理なんだ。
でもね、実際のプログラムは、もっと複雑な処理をすることもあるんだ。例えば、「ファイルを読み込む」という処理。ハードディスクからファイルを読むって、結構時間がかかるんだ。メモリに直接アクセスするのと比べると、1000倍以上遅いんだよ。信じられないでしょ。
同期処理のやり方だと、こんなことになるんだ。1行目で「ファイルを読み込む」という命令を出す。これに3秒かかるとしよう。その3秒の間、プログラムは何もしてない。ただ待っているんだ。2行目の「ファイルの内容を処理する」という命令は、ファイルの読み込みが100%完了するまで、一切実行されないんだ。これを「ブロック」(つまり、処理が止まる)って言うんだ。
ブロックが起きると、ユーザーはどう感じると思う?「あ、プログラムが固まった」って感じちゃうんだ。スマートフォンでもパソコンでも、画面がぼやっとしたら「あ、動いてないのかな」ってなるでしょ。その時間が長いと、ユーザーはイライラしちゃう。だから、実務的なプログラムでは、同期処理と非同期処理を使い分けているんだよ。同期処理は「絶対に順番を守らなきゃいけない処理」に使うし、非同期処理は「時間がかかるけど、順番を気にしなくていい処理」に使うんだ。
でもね、プログラミングの勉強を始めたばっかりの人は、ほぼ同期処理だけで十分なんだ。なぜなら、順番が明確だから、どうしてエラーが出たのかが理解しやすいからなんだよ。複雑な非同期処理は、基本が身についてからでいいんだ。
同期処理の流れを図で理解する
同期処理の流れって、こんなふうに描くことができるんだ。時系列で並べると、処理1が完全に終わってから処理2が始まるんだよ。処理1が1秒で終わって、処理2が2秒で終わるなら、全体では3秒かかるんだ。この「順番に並ぶ」っていう考え方が、同期処理の本質なんだ。
同期処理のメリットとデメリット
さあ、同期処理には良い面と悪い面があるんだ。正しく使い分けるために、両方を理解しようね。
メリット:分かりやすい
同期処理の一番大きな利点は「流れがシンプル」ってことなんだ。1→2→3って進んでいく。考えることが少ないんだよ。「Aという処理は必ずBの後に実行される」ってことが保証されるからね。例えば、銀行の振込なら、口座から金額を引いて、相手の口座に金額を加えて、記録を保存する。このプロセスは絶対にこの順番で実行されなきゃいけない。もし「2が1より先に起きたら」なんて想像すると、「凄い金額が加算されたのに、元の口座からは引かれなかった」みたいなバグが起きるんだ。同期処理なら、こういう心配がないんだよ。
メリット:デバッグが簡単
もし何か問題が起きたとき、同期処理なら原因を探しやすいんだ。「ここでエラーが出た」って場所が明確だからね。「3番目の処理でバグが出た」なら、3番目の処理を見ればいい。1番目と2番目は確実に終わってるから、そっちは見なくていいんだ。非同期処理だと「どこで問題が起きたのか」が複雑になることがあるんだよ。
デメリット:時間がかかる場合がある
ファイルの読み込みみたいに、時間がかかる処理があると、次の処理が待たされるんだ。スマートフォンなら「画面が固まってる」みたいに感じるんだよ。例えば、オンラインゲームで、サーバーからデータを取ってくるのに5秒かかるとしたら、その5秒の間、画像の更新も何もできないんだ。ユーザーはイライラしちゃうんだよ。ゲームのキャラクターが全く動かないんだから。
デメリット:複雑な処理が書きにくい
複数のファイルを同時に読み込みたい場合を考えてみて。同期処理なら、ファイルA読み込みに5秒かかって、ファイルB読み込みに5秒かかって、ファイルC読み込みに5秒かかる。合計15秒かかるんだ。でも、本当は3つのファイルを同時に読み込むことだって可能なのに、同期処理では順番を待たなきゃいけないんだよ。効率が良くないんだ。
つまり、同期処理は「安全」だけど「効率が落ちる可能性がある」ってわけなんだ。だから、プログラマーは「どこで安全を優先するか」「どこで効率を優先するか」を判断しなきゃいけないんだよ。
同期処理と非同期処理の違い
ね、「同期処理」って言葉がある以上、「非同期処理」ってのもあるんだ。ここで、その2つの違いをハッキリさせようね。
「同期処理」(同期=一緒に進む)は、さっき説明した通り「1→2→3」って順番にやる方法なんだ。全部を一緒に、順番に進ませるってイメージだね。つまり、ある処理に「進むタイミング」は、前の処理が「終わるタイミング」と完全に同期しているんだ。
一方、「非同期処理」(非同期=一緒じゃなく進む)は、「1を始めたけど、1が終わる前に2も始める」ってやり方なんだ。つまり、複数の処理が「ほぼ同時」に進むんだよ。処理の進むタイミングが「同期」していないんだ。
具体例を出そうか。スマートフォンで動画をダウンロードしながら、メールを書いているってシーン。これが非同期処理なんだ。ダウンロードが終わるまで待たずに、メールの入力ができるんだよ。コンピュータの視点からすると、ダウンロード処理とメール入力処理が「同時」に進んでいるんだ。
コンピュータの時間で表すと、こんなことが起きている。同期処理なら、13時0分0秒にファイル読み込み開始、13時0分5秒に終了。次に13時0分5秒にデータ処理開始、13時0分7秒に終了。全体では13時0分7秒かかるんだ。
でも非同期処理なら、13時0分0秒にファイル読み込み開始と同時に、データ処理も13時0分0秒に開始しちゃう。ファイル読み込みは13時0分5秒に終了するけど、データ処理は13時0分7秒に終了する。全体では13時0分7秒で済むんだ。5秒の短縮だ。これが「効率の良さ」なんだよ。
でもね、複雑さも増すんだよ。「あ、ファイルの読み込みはまだ終わってないのに、データ処理が始まっちゃった」みたいなバグが起きやすくなるんだ。だから、プログラマーは「非同期」を使う時は、すごく気をつけなきゃいけないんだよ。「この処理は、前の処理の結果を必要としているか」とか「タイミングがズレたら、どんなことが起きるか」とか、いっぱい考えなきゃいけないんだ。
まとめると、同期処理と非同期処理は「処理を進める順序」の決め方が違うんだ。同期は「守られた順番」で、非同期は「同時進行」ってわけなんだよ。どっちが良いかじゃなくて、「どこに使うか」が大事なんだ。
