1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

処理は順番に動くとは限らない?|新人・初級PG向け 同期・非同期の基本

1
Posted at

プログラムを学び始めた頃、

私は、

「プログラムは上から順番に処理されるもの」

だと思っていました。

例えば、

Console.WriteLine("処理A");
Console.WriteLine("処理B");
Console.WriteLine("処理C");

なら、

処理A
 ↓
処理B
 ↓
処理C

と順番に実行されます。

これは分かりやすいですよね。

ところが、実際のプログラムを見ていると、

async
await
Task

といったものが登場します。

そして、

「上から順番に書いてあるのに、思っていた動きと違う」

「この処理はもう終わっていると思ったのに、まだ終わっていない」

といったことが起こります。

ここで出てくるのが、

同期処理と非同期処理

という考え方です。

今回は、いきなりasyncやawaitの書き方を覚えるのではなく、

そもそも同期・非同期とは何なのか?

から整理してみます。

同期処理とは?

まずは同期処理です。

簡単にいうと、

一つの処理が終わるのを待ってから、次の処理へ進む

という動きです。

例えば、

処理A
 ↓
処理Aが終わる
 ↓
処理B
 ↓
処理Bが終わる
 ↓
処理C

という流れです。

コードで考えると、

ProcessA();
ProcessB();
ProcessC();

基本的には、

ProcessA()が終わってからProcessB()、

ProcessB()が終わってからProcessC()へ進みます。

つまり、

前の処理が終わるまで次の処理は待つ。

これが同期処理の基本的なイメージです。

コックさんで考えてみる

もう少しイメージしやすいように、

レストランの厨房で考えてみます。

コックが一人いるとします。

まず、お肉をオーブンに入れました。

同期の場合

お肉をオーブンに入れる
        ↓
焼き上がるまで10分待つ
        ↓
お肉が焼き上がる
        ↓
サラダを作る

お肉を焼いている10分間、

コックはオーブンの前で待っています。

お肉が焼き上がってから、

ようやくサラダを作り始めます。

これが同期処理のイメージです。

一つの仕事が終わるまで待ってから、次の仕事へ進む。

では、非同期の場合はどうでしょう。

非同期の場合

お肉をオーブンに入れる
        │
        ├──────→ オーブンで調理中
        │
        ↓
   サラダを作る
        │
        ←────── お肉が焼き上がる
        ↓
     盛り付ける

お肉をオーブンに入れたあと、

コックはその場で10分間待ちません。

お肉が焼けるのを待っている間に、

サラダを作ります。

そして、

お肉が焼き上がったら、盛り付けをします。

これが非同期処理を理解するための基本的なイメージです。

待っている時間に、ほかの仕事を進める。

ここが大きなポイントです。

非同期にすると処理が速くなる?

ここで一つ注意があります。

非同期処理というと、

「処理を速くする仕組み」

のように感じるかもしれません。

でも、少し違います。

先ほどの例なら、

非同期にしたからといって、

10分かかるお肉が5分で焼けるわけではありません。

お肉が焼けるまでの時間は10分のままです。

違うのは、

その10分間、

コックがただ待っているのか、

別の仕事を進められるのかです。

つまり非同期処理は、

待ち時間をなくすのではなく、待っている間にほかの仕事を進められるようにする

と考えると分かりやすいと思います。

なぜプログラムに非同期処理が必要なの?

では、なぜプログラムでも、

このような仕組みが必要なのでしょうか。

プログラムには、

結果が返ってくるまで時間のかかる処理があります。

例えば、

・ファイルを読み込む
・データベースからデータを取得する
・Web APIからデータを取得する
・ネットワークを使って通信する

などです。

例えば、

データベースからデータを取得するのに10秒かかったとします。

同期処理なら、

データ取得開始
      ↓
   10秒待つ
      ↓
データ取得完了
      ↓
次の処理

となります。

つまり、

結果が返ってくるまで、そこで待つことになります。

これが画面を持つアプリケーションでは、問題になることがあります。

例えばWPFでは?

WPFなどの画面を持つアプリで、

ボタンを押したときに時間のかかる処理を実行するとします。

ボタンを押す
     ↓
データ取得開始
     ↓
   10秒待つ
     ↓
データ取得完了

もし、この処理によって画面を動かしている処理まで止めてしまうと、

・ボタンを押しても反応しない
・画面を操作できない
・画面が固まったように見える

といったことが起こります。

ユーザーからすると、

「あれ?アプリ固まった?」

となります。

そこで、

時間のかかる処理を待っている間も、

画面側の仕事を続けられるようにする。

そのためにも、

非同期処理

という考え方が重要になります。

非同期=同時に処理する、ではない

ここも最初は混乱しやすいところです。

非同期処理を見ると、

「複数の処理を同時に実行すること?」

と思うかもしれません。

でも、

非同期と並列処理は同じものではありません。

先ほどのコックの例で考えてみます。

非同期では、

コックは一人でした。

コック1人


お肉をオーブンへ
      ↓
焼いている間に
サラダを作る

一方、

例えばコックが二人いて、

コックA → お肉を調理


コックB → サラダを作る

と、本当に複数の仕事を同時に進めるなら、

これは先ほどとは少し違う話になります。

今回まず覚えておきたいのは、

非同期処理は「待っている間に、ほかの仕事を進められるようにする」ということ。

並列処理との違いについては、また別の記事で整理したいと思います。

ではasync / awaitは何をしているの?

C#では、

非同期処理を書くときに、

async
await
Task

といったものをよく使います。

例えば、

var data = await GetDataAsync();

のようなコードです。

ここで、

少し不思議に思いませんか?

awaitは日本語にすると、

「待つ」

という意味です。

「あれ?」

「待つなら同期処理と同じじゃないの?」

と思うかもしれません。

実は、

ここが非同期処理を理解するときの大事なポイントです。

awaitは単純に、

「プログラム全部をそこで止めて待つ」

という意味ではありません。

では、

asyncとawaitは実際に何をしているのでしょうか。

これは次回、

実際のコードを見ながら整理してみます。

デバッグするときにも重要

同期・非同期を理解しておくことは、

コードを書くときだけでなく、

デバッグするときにも重要です。

例えば、

処理A
 ↓
処理B
 ↓
処理C

だと思って調査していたとします。

ところが、

途中に非同期処理があった場合、

自分が想像していた処理の進み方と、

実際の動きが違っていることがあります。

すると、

「なんでこの値、まだ入ってないの?」

「この処理、もう終わっていると思ったのに」

といった混乱が起こります。

だからコードを追うときには、

処理の内容だけでなく、

「この処理は同期なのか、非同期なのか」

という視点を持つことも大切です。

まとめ

今回は、

同期処理と非同期処理の基本

について紹介しました。

覚えておきたいポイントは、

・同期処理は、前の処理が終わるのを待って次へ進む
・非同期処理では、待っている間にほかの仕事を進められる
・非同期にしても、その処理自体が速くなるとは限らない
・非同期処理と並列処理は同じものではない
・コードを追うときは「同期か非同期か」という視点も重要

です。

プログラムは、

「上から順番に書いてあるから、すべての処理が終わるまで順番に待つ」

とは限りません。

まずは、

同期=終わるまで待って次へ進む

非同期=待っている間にほかの仕事を進められる

というイメージを持っておくだけでも、

コードを見るときの視点が少し変わると思います。

次回は、

「awaitは待つのに、なぜ画面は止まらないの?」

をテーマに、

C#のasync / awaitが何をしているのか、

実際のコードを使って整理してみます。

関連記事

まずはこちら
新人・初級PGが最初に覚えた方がいいこと|言語より先に理解したいプログラムの仕組み

処理の流れを理解したい人へ
ソースは読めるのに処理が追えないのはなぜ?|フローを追っていたはずなのに迷子になる原因
処理は追えるのに「なぜそれをしているのか」が分からない人へ | コードから目的を読み解く考え方

デバッグで迷子になりやすい人へ
不具合は分かるのに、何を調べればいいか分からない人へ

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?