同期/非同期プログラミング

Dec 06 2022
このブログでは、同期プログラミングと非同期プログラミングが何であるかを最もよく説明しようとしています。
発信者が受信者にメッセージを送信し、応答を待っている場合、他のことを行うことができますか? これらの呼び出しはどこでも発生するため、サーバー/クライアントではなく発信者/受信者と言っています。設計上、最初にコンピューティングを構築したとき、すべてが同期的でした。
同期/非同期

発信者が受信者にメッセージを送信し、応答を待っている場合、他のことを行うことができますか? これらの呼び出しはどこでも発生するため、サーバー/クライアントではなく発信者/受信者と言っています。設計上、最初にコンピューティングを構築したとき、すべてが同期的でした。これは、発信者とサーバーが同期しているサイン波または同じリズムと見なすことができます。非同期とは、同期していないことを意味します。

同期 I/O
呼び出し側が要求を受信側に送信してから、それをブロックします。これは、発信者がブロックされ、何もしないため、合計時間が無駄になる場合です。昔は、CPU はプロセスがブロックされているだけだと考えてプロセッサからプロセスを削除し、ブロックされていない新しいプロセスを追加しました (コンテキスト切り替え)。そのため、呼び出し元はその間実行できません。最後に、受信者が応答すると、オペレーティング システムはプロセスをプロセッサに戻すことができます。したがって、発信者はブロックを解除します。これは、クライアントとサーバーが完全に同期していることを示しています。

OS 同期 I/O の例:
1. プログラムは、ディスクからファイルを読み取るように CPU に要求します。
2. プログラムのメイン スレッドが CPU から切り離されます。
3. 読み取りが完了し、プログラムが再び実行を開始します。

// A simple Js example
// Program starts
// Programs uses CPU to execute work.

SampleFunction();
// Program reads from the disk
// Program can't do anything until file loads
readfile("SyncExample.dat")

// Program resumes

特に NodeJ の観点から言えば、Linux では epoll を使用し、Windows の場合は補完主義スタックを使用します。nodeJs が行うもう 1 つのことは、何かがブロック操作を実行する必要がある場合にブロックする新しいスレッドをスピンアップすることです。デフォルトでは、Nodejs にはlibuvライブラリに 4 つのワーカー スレッドがあり、I/O 操作に使用されますが、構成可能です。

OS 非同期呼び出し (NodeJS) の例
a) プログラムがセカンダリ スレッドをスピンアップします
。b) セカンダリ スレッドがディスクから読み取ります。明らかに、OS は現在のプロセッサから削除します
c) メイン プログラムは引き続き実行され、実行されます。
d) スレッドが終了し、メイン スレッドを呼び出します。

// A simple Javascript example
// Program starts
// Programs uses CPU to execute work.

SampleFunction();
// Program reads from the disk
// Program hapilly moves on to the samplefunction2
readfile("SyncExample.dat", onReadFinish(console.log))
//file is not probably read yet

SampleFunction2();
//onReadFinish function called
// executing it

ここで、純粋にクライアントとサーバー (バックエンド) の知覚から物事を説明します。
したがって、シンクロニシティは、待機または移動できるクライアント プロパティとしても知られています。現在、同期のクライアントはなく、ほとんどのライブラリは非同期です。ほとんどの場合、クライアントはリクエストを送信し、レスポンスを取得します。レスポンスが実行されるたびにコールバックが呼び出されます。特に Node.js では、応答をチェックアウトするイベント ループのメイン ループがあります。
これは混乱を招く可能性があります。誰かがこの美しい実際の例で説明したとき、同期は会議で質問をするようなものであり、プレゼンターが応答した場合に会議が進行するのはいつものことでした。非同期は、受信者が時間があればいつでも応答できる電子メールで質問をするようなものです。

非同期バックエンド処理

バックエンド エンジニアとして、バックエンドを非同期にすることについて話さないと不公平です。多くのコード/リポジトリでは、クライアントは主に非同期ですが、バックエンドは依然としてクライアントを待機させます。したがって、クライアントがデータのプッシュを要求すると、たとえばデータベース呼び出しを行うと、コミット後にステータス 200 応答を返すバックエンドからの応答を待つように何度も要求されます。ここで、レンズをバックエンドに移動すると、フロントエンドは非同期ですが、バックエンドは依然として同期しています。では、即時応答を返すにはどうすればよいでしょうか。
解決策の 1 つは、キューという名前のこの美しいデータ構造を使用することです。クライアントがリクエストを送信した場合、すぐに実行することは約束しませんが、キューにフラッシュします。これは、バックエンドが以前のリクエストを完了している可能性があり、クライアントがブロックされなくなったためです。リクエストをキューに入れたことを示すレスポンスを送信できます。ここに promise/JobID があります。詳細については、メッセージ キューについてを参照してください。
ユースケースによっては、これ以外にも非常に一般的なソリューションがあります。

非同期ワークロードの実際の例: a) Postgres ↗
での非同期コミット。b) Linux での非同期 I/O (io-uring)。c) 非同期 I/O fsync (fs-cache): ファイルに何かを書き込むときは常に、ディスクに直接書き込まれるのではなく、ファイル システム キャッシュに書き込まれます。オペレーティング システムにはキャッシュがあり、書き込みはページに行われます。次に、オペレーティング システムはすべてのページを一度にフラッシュします。

全体を次のように要約できます。
a) 同期プログラミングのアプローチでは、タスクを順番に実行します。各タスクは、前のタスクが終了するのを待ってから実行されます。
b) タスクが非同期プログラミング モデルで実行されると、前のタスクが終了するのを待たずに別のタスクに移ることができます。

読んでくれてありがとう; お役に立てば幸いです。ご不明な点がございましたら、 LinkedIn / Instagram
でお気軽にお問い合わせください。