違いは何ですか:
何か非同期とノンブロッキング(およびイベントベース )?
非同期、非ブロッキング、イベントベース(または3つすべて)のいずれかを持つために、プログラミングで最も重要なことは何ですか?
例を提供できれば、それは素晴らしいことです。
私はこの素晴らしい StackOverflow の同様のトピックに関する記事を読んでいたので、この質問がされていますが、上記の私の質問には答えていません。
非同期非同期は文字通り同期しないことを意味します。電子メールは非同期です。メールを送信しますが、今すぐ応答を受け取ることは期待できません。しかし、それはノンブロッキングではありません。本質的にそれが意味するのは、「コンポーネント」が即座に応答を期待することなく互いにメッセージを送信するアーキテクチャです。 HTTPリクエストは同期的です。要求を送信して応答を取得します。
非ブロッキングこの用語は、主にIOで使用されます。つまり、システムコールを行うと、スレッドをスリープ状態にせずに(高い確率で)どんな結果でもすぐに返されます。たとえば、ノンブロッキングの読み取り/書き込み呼び出しは、できることは何でも返し、呼び出し元が呼び出しを再度実行することを期待します。たとえば、try_lockは非ブロッキング呼び出しです。ロックを取得できる場合にのみロックします。システムコールの通常のセマンティクスはブロックしています。 readは、データを取得するまで待機し、呼び出しスレッドをスリープ状態にします。
イベントベースこの用語はlibeventに由来します。ノンブロッキング読み取り/書き込み呼び出し自体は、コールバック(再試行)する必要がある場合に「いつ」通知しないので役に立たない。 select/epoll/IOCompletionPortなどは、これらの呼び出しが「興味深い」データを返すと予想される「いつ」OSから見つけるためのさまざまなメカニズムです。 libeventなどのライブラリは、さまざまなOSが提供するこれらのイベント監視機能のラッパーを提供し、オペレーティングシステム間で動作する一貫したAPIを提供します。ノンブロッキングIO Event-baseと連動します。
これらの用語は重複すると思います。たとえば、HTTPプロトコルは同期ですが、非ブロッキングIOを使用したHTTP実装は非同期にすることができます。read/ write/try_lockなどの非ブロッキングAPI呼び出しは同期です(すぐに応答します) 「データ処理」は非同期です。
非同期ハードウェアでは、コードは何らかのエンティティに何かを行うように要求し、アクションの実行中に他のことを自由に行うことができます。アクションが完了すると、エンティティは通常、何らかの方法でコードを通知します。ノンブロッキングアーキテクチャは、コードが関心を持っている可能性がある自発的に発生するアクションをメモし、コードがそのようなアクションが発生したことを尋ねることを許可しますが、コードは明示的にそれらについて尋ねた場合にのみそのようなアクションを認識します。イベントベースのアーキテクチャは、イベントが自発的に発生したときにコードに肯定的に通知します。
コードが1,000バイトを受信するシリアルポートを考えます。
ブロック読み取りアーキテクチャでは、コードは1,000バイトが到着するか、または放棄することを決定するまで待機します。
非同期読み取りアーキテクチャでは、コードはドライバーに1,000バイトが必要であることを通知し、1,000バイトが到着すると通知されます。
ノンブロッキングアーキテクチャでは、コードはいつでも何バイトが到着したかを尋ねることができ、適切と思われる場合はそのようなデータの一部またはすべてを読み取ることができますが、すべてのデータが到着したことを知る唯一の方法は尋ねることです;コードが1000番目のバイトが到着したときに1/4秒以内に検出したい場合は、1/4秒ごとにチェックする必要があります。
イベントベースのアーキテクチャでは、シリアルポートドライバーは、データが到着するたびにアプリケーションに通知します。ドライバーは、アプリケーションが必要とするバイト数を知らないため、アプリケーションは、アプリケーションが必要とする量よりも多いまたは少ない量の通知を処理できる必要があります。
私にとって、非ブロッキングとは、スレッド内のアクションの実行が他のスレッドの実行に依存せず、特に重要なセクションを必要としないことを意味します。
非同期とは、実行が呼び出し元のフローの外側で発生し、延期される可能性があることを意味します。通常、実行は別のスレッドで行われます。
並行データの読み取りは非ブロッキング(ロックする必要はありません)でありながら、同期的です。逆に、同期方式で同時にデータを書き込むことはブロッキングです(排他ロックが必要です)。メインフローの観点からブロックしないようにする方法は、書き込みを非同期にし、実行を延期することです。
イベントの概念は別のものであり、大まかに言えば、何かが発生したときに通知されることを意味します。書き込みが非同期で実行された場合、書き込みが実行されると、イベントを発生させてシステムの他の部分に通知できます。他の部分はイベントに応答します。システムは、コンポーネント間で通信する唯一の方法としてイベントのみで構築できますが(アクターモデルのように)、必ずしもそうである必要はありません。
3つの用語は関連していますが、私にとっては異なる概念です。しかし、人々は多少互換性のある方法でそれらを使用する可能性があります。
一般に、非ブロッキングアーキテクチャは、workerスレッドで長時間実行される可能性があるが-callingスレッドをブロックしないメソッド呼び出しに基づいています。呼び出しスレッドがワーカースレッドが実行しているタスクに関する情報を取得する必要がある場合、それを実行するのは呼び出しスレッド次第です。
イベントベースのアーキテクチャは、発生したイベントに応じて実行されるコードの概念に基づいています。通常、コード実行のタイミングは確定的ではありませんが、イベントはブロッキングメソッドを呼び出す場合があります。システムがイベントベースであるからといって、システムのすべてがブロックされているわけではありません。
一般に、非同期アーキテクチャは、イベントベースのノンブロッキングアーキテクチャです。
非同期呼び出しが行われると、同期サービスを提供するAPIにイベントハンドラーが登録され、呼び出し元が興味を持っていることが発生したことを呼び出し元に通知します。その後、呼び出しはすぐに戻り(非ブロッキング動作)、呼び出し元は実行を継続できます。イベントが呼び出し元プロセスに戻されると、そのプロセスの一部のスレッドで処理されます。
イベントが同じスレッドで処理されるかどうかを理解することは重要です。これは、実行の非ブロッキングの性質に影響を与えるためです。しかし、単一のスレッドで非同期実行管理を行うライブラリを個人的には知りません。
述べられているように厳密に正しくないため、上記の段落を削除しました。私の意図は、システム内のoperationsがOSファシリティを呼び出して実行を継続するなど、非ブロッキングであるにもかかわらず、シングルスレッド実行の性質とは、イベントが発生すると、スレッド上の計算時間を求めて他の処理タスクと競合することを意味します。
したがって、最初と2番目の質問に答えるには:
ノンブロッキングは非同期と実質的に同じです-呼び出しを行うと、後で結果が得られますが、その間に何か他のことを行うことができます。ブロッキングは反対です。あなたは旅を続ける前に電話が戻るのを待ちます。
現在、非同期/非ブロックコードは非常に素晴らしい音に聞こえます。しかし、私は警告の言葉を持っています。非同期/非ブロッキングは、携帯電話などの制約のある環境で作業する場合に最適です。CPU/メモリの制限を考慮してください。また、コードが何らかの方法でUIウィジェットに反応する必要があるフロントエンド開発にも適しています。
非同期は、すべてのオペレーティングシステムが動作するための基本です-彼らはバックグラウンドでたわごとを完了し、あなたが要求したことを行い、その呼び出しが失敗したとき、あなたはそれをしないと言われます例外、または何らかの種類のリターンコード/エラーオブジェクトによって動作します。
コードが応答にしばらく時間がかかるものを要求した時点で、OSは他の処理で忙しくなる可能性があることを認識しています。コード-プロセス、スレッド、または同等のブロック。あなたのコードは、そのネットワーク接続が確立されるのを待っている間、またはHTTPリクエストからのその応答を待っている間、またはそのファイルの読み取り/書き込みを待っている間、OSで他に何が起こっているかを完全に忘れていますなど。あなたのコードはマウスクリックを「単純に」待っているかもしれません。その間に実際に起こっていたのは、OSがシームレスに「イベント」を管理、スケジューリング、および反応していることです。OSは、メモリ、I/O(キーボード、マウス、ディスク、インターネット)の管理など、その他のタスク、障害回復など.
オペレーティングシステムは非常にハードコアです。彼らはあなたのプログラマーから複雑な非同期/ノンブロッキングのものをすべて隠すのが本当に上手です。そして、それがほとんどのプログラマーがソフトウェアを使用して現在の場所に到達した方法です。現在、CPUの制限に達しています。人々は、パフォーマンスを改善するために並行して行うことができると言っています。これは、非同期/非ブロック化が非常に好ましいことのように思われることを意味し、はい、あなたのソフトウェアがそれを要求するなら、私は同意できます。
バックエンドWebサーバーを作成している場合は、注意して進めてください。はるかに安価に水平にスケーリングできることを忘れないでください。ただし、Netflix/Amazon/Google/Facebookはこのルールの明らかな例外ですが、ハードウェアの使用が少ないほうが安く処理できるためです。
非同期/ノンブロッキングコードがバックエンドシステムで悪夢である理由を説明します。
1)生産性に関するサービス拒否になります。もっと考える必要があり、途中で多くの間違いを犯します。
2)リアクティブコードのスタックトレースは判読不能になります-何が何を、いつ、なぜ、どのように呼び出したかを知るのは困難です。デバッグしてください。
3)物事がどのように失敗するか、特に多くの物事があなたがそれらを送った方法に順不同で戻ってくるとき、あなたはもっと考えなければなりません。旧世界では、一度に1つのことを行いました。
4)テストするのが難しい。
5)維持するのが難しい。
6)痛い。プログラミングは喜びで楽しいはずです。痛みが好きなのはマゾヒストだけです。コンカレント/リアクティブフレームワークを書く人はサディストです。
そして、はい、私は同期と非同期の両方を書きました。 99.99のバックエンドアプリケーションがこのパラダイムでうまくいくので、同期が好きです。フロントエンドアプリには、問題のないリアクティブコードが必要です。
はい、コードは非同期、非ブロッキング、およびイベントベースにすることができます。
プログラミングで最も重要なことは、コードが機能し、許容可能な時間内に応答することを確認することです。その重要な原則に固執すれば、間違いはありません。