🤖

同期・非同期とブロッキング・ノンブロッキングの違い

に公開

「Goならわかるシステムプログラミング」を読んでいて、同期・非同期とブロッキング・ノンブロッキングの言葉の定義について理解が曖昧だったので、整理してみました。
https://www.lambdanote.com/products/go-2

同期・非同期

「同期か非同期か」は結果の受け取り方を指します。

同期

OSに処理を依頼し、その入出力の準備ができた時点で処理が呼び出し元(アプリケーション)に戻ってくる方式。

つまり、実データを取りに行くというムーブになります。

非同期

OSに処理を依頼し、その入出力が完了したら通知(結果の知らせ)を受け取る方式。

つまり、データが準備できたら教えてもらい、その後に実データを取りに行くというムーブになります。

ブロッキング・ノンブロッキング

「ブロッキングかノンブロッキングか」は待ち方のスタイルを指します。

ブロッキング

頼んだ仕事(処理)が完了するまで待ち続けるスタイル。

ノンブロッキング

頼んだ仕事(処理)が完了するまで待たずに、他の仕事をするスタイル。

I/O処理モデルの4つのパターン

同期・ブロッキング

処理を依頼したら、その読み書きが完了するまで何もせず待つ方式です。重いI/O処理があるとその間プログラム全体が止まってしまいますが、コード自体は直線的で分かりやすいという利点があります。

同期・ノンブロッキング

ノンブロッキングモードで処理を開始し、完了しているかどうかを繰り返し確認することで進みます。一度の呼び出しで完了を待たず、「今終わっている分だけデータを取得する or まだ終わっていないという状態を返す」ので、呼び出し側は何度もAPIを呼び出して完了をチェックします。

非同期・ブロッキング

処理自体はOSに依頼しておき、何か準備ができた(イベントが発生した)ときに通知を受け取る方式です 。具体的には、OSの提供するselectやepollといった I/O多重化の仕組みを使い、準備のできたI/Oの通知をひとまとめに待ち受けます。この待ち受け自体はブロッキング(通知が来るまで待つ)ですが、通知を受け取ってから実際のI/O処理を行うので、複数のI/Oを効率よくさばけます。

非同期・ノンブロッキング

メインの流れとは別のスレッドや仕組みで処理を進め、完了したら通知だけ受け取る方式。依頼を出した後、呼び出し側は全く待たずに他の作業を続けられ、処理が完了したタイミングで割り込み的に結果を受け取ります。

具体例

料理の注文にたとえて、同期/非同期・ブロッキング/ノンブロッキングの違いを説明します。

同期・ブロッキング

ファストフード店で注文をして、その場で料理が出てくるのをカウンターの前でじっと待っている状況です。他のことはせず、注文した品ができあがるまでその場を離れません。あなた(呼び出し元)は注文が完了するまでブロックされています。料理が出たらすぐ受け取り、待ち時間はそこで終了です。これは「結果が準備できるまで待つ」という同期かつブロッキングな動きです。

同期・ノンブロッキング

ファストフード店で注文をして、店員さんに「まだですか?」と何度も確認しに行くようなウザい客状況です。例えば、注文後に席に座って待ちながら、数分おきにカウンターに行って「料理できましたか?」と尋ねる(これがポーリングに相当)。料理がまだならまた席に戻り、しばらくしてまた確認する、を繰り返します。一度の確認(問い合わせ)自体はすぐ終わるのでその意味ではブロックしていませんが、何度も自分から確認しに行く点で同期的です。効率は悪いですが、待ち時間に席で他のこと(例えばスマホを見るなど)は一応できているので、処理自体はノンブロッキングになっています。

非同期・ブロッキング

レストランで注文後、呼び出しベル(ブザー)を渡されて待つ状況です。料理ができあがったらブザーが鳴るというイベント通知で知らせてもらえます。この間、あなたは席で待っていますが、定期的に確認しに行く必要はありません(通知が非同期的に来ます)。ただし、ブザーが鳴るまでは店を出ずに待機している点でブロッキングです。他のことはあまりできず、「呼ばれるのを待つ」という状態ですね。これは非同期(出来上がりをイベントで知る)だけれど、待っている間はブロッキングしている例です。

非同期・ノンブロッキング

フードコートで注文後、呼び出しベル(ブザー)を渡されて待つ状況です。料理ができあがったらブザーが鳴るというイベント通知で知らせてもらえます。この間、あなたは席で待っているのではなく、他の店に行ったり買い物をしたり、他の用事を済ませています。ブザーが鳴ったら戻ってきて料理を受け取る、という流れです。この場合、待っている間も他のことをしているので、非同期かつノンブロッキングな状態です。

GitHubで編集を提案

Discussion