非同期呼び出しと非ブロッキング呼び出しの違いは何ですか?また、ブロッキング呼び出しと同期呼び出しの間(例を示してください)?
非同期呼び出しと非ブロッキング呼び出しの違いは何ですか?また、ブロッキング呼び出しと同期呼び出しの間(例を示してください)?
回答:
多くの場合、これらは同じものの異なる名前ですが、状況によってはかなり異なります。したがって、状況によって異なります。用語は、ソフトウェア業界全体で完全に一貫した方法で適用されていません。
たとえば、クラシックソケットAPIでは、非ブロッキングソケットは、特別な「ブロックする」というエラーメッセージが表示されてすぐに戻るソケットですが、ブロッキングソケットはブロックします。select
またはなどの別の関数を使用する必要がありますpoll
いつ再試行するのが適切を確認するがあります。
ただし、非同期ソケット(Windowsソケットでサポートされている)、または.NETで使用される非同期IOパターンの方が便利です。メソッドを呼び出して操作を開始すると、フレームワークはそれが完了するとコールバックします。ここでも基本的な違いがあります。非同期のWin32ソケットは、ウィンドウメッセージを渡すことによって結果を特定のGUIスレッドに「マーシャリング」しますが、.NET非同期IOはフリースレッドです(コールバックが呼び出されるスレッドがわかりません)。
したがって、それらは常に同じことを意味するわけではありません。ソケットの例を詳しく説明すると、次のようになります。
同期/非同期は、2つのモジュール間の関係を記述することです。
ブロッキング/ノンブロッキングは、1つのモジュールの状況を説明することです。
例:
モジュールX: "I"。
モジュールY:「書店」。
XがYに尋ねる:「c ++プライマー」という名前の本はありますか?
1)ブロッキング:YがXに応答する前に、Xは応答を待ち続けます。現在、X(1つのモジュール)がブロックしています。XとYは、2つのスレッドまたは2つのプロセスですか、1つのスレッドまたは1つのプロセスですか?私たちは知りません。
2)非ブロッキング:YがXに応答する前に、Xはそこを離れて他のことを行います。Xが2分ごとに戻ってきて、Yが仕事を終えたかどうかを確認しますか?または、Yが電話するまでXは戻ってきませんか?わかりません。Xが他のことをできるのは、Yが仕事を終える前だけです。ここで、X(1つのモジュール)は非ブロッキングです。XとYは、2つのスレッド、2つのプロセス、または1つのプロセスですか?私たちは知りません。しかし、XとYを1つのスレッドにすることはできません。
3)同期:YがXに応答する前に、Xは応答を待ち続けます。つまり、XはYが仕事を完了するまで続行できません。XとY(2つのモジュール)は同期しています。XとYは、2つのスレッドまたは2つのプロセスですか、1つのスレッドまたは1つのプロセスですか?私たちは知りません。
4)非同期:YがXに応答する前に、Xはそこを離れ、Xは他のジョブを実行できます。XはYが電話するまで戻ってきません。XとY(2つのモジュール)は非同期です。XとYは、2つのスレッド、2つのプロセス、または1つのプロセスですか?私たちは知りません。しかし、XとYを1つのスレッドにすることはできません。
上記の2つの太字に注意してください。2)のボールドセンテンスに2つのケースが含まれているのに、4)のボールドセンテンスには1つのケースしか含まれていないのはなぜですか?これは、非ブロッキングと非同期の違いの鍵です。
以下は、非ブロッキングと同期に関する典型的な例です。
// thread X
while (true)
{
msg = recv(Y, NON_BLOCKING_FLAG);
if (msg is not empty)
{
break;
}
sleep(2000); // 2 sec
}
// thread Y
// prepare the book for X
send(X, book);
このデザインはノンブロッキングであることがわかります(ほとんどの場合、このループは意味のないことをしますが、CPUの目から見ると、Xは実行中であり、つまりXはノンブロッキングです)。 Yから本を取得するまで、他のことは何もしません(Xはループからジャンプできません)。
通常、この場合、非ブロッキングは愚かなループのために多くのリソースを費やすため、Xブロッキングをはるかに優れたものにします。ただし、この例は、事実を理解するのに役立ちます。非ブロッキングは非同期を意味しません。
4つの単語を使用すると混乱しやすくなります。覚えておくべきことは、4つの単語がアーキテクチャの設計に役立つということです。優れたアーキテクチャを設計する方法について学ぶことは、それらを区別する唯一の方法です。
たとえば、次のような種類のアーキテクチャを設計できます。
// Module X = Module X1 + Module X2
// Module X1
while (true)
{
msg = recv(many_other_modules, NON_BLOCKING_FLAG);
if (msg is not null)
{
if (msg == "done")
{
break;
}
// create a thread to process msg
}
sleep(2000); // 2 sec
}
// Module X2
broadcast("I got the book from Y");
// Module Y
// prepare the book for X
send(X, book);
この例では、
必要に応じて、X1で作成されたスレッドを4つの単語で説明することもできます。
より重要なことは、非同期ではなく同期をいつ使用するかです。ノンブロッキングの代わりにブロッキングを使用するのはいつですか?
Nginxが非ブロッキングになるのはなぜですか?Apacheがブロックされるのはなぜですか?
適切な選択を行うには、ニーズを分析し、さまざまなアーキテクチャのパフォーマンスをテストする必要があります。さまざまなニーズに適したアーキテクチャはありません。
この質問をJava 7のNIOおよびNIO.2のコンテキストに当てはめると、非同期IOは非ブロッキングよりも1ステップ進んでいます。Java NIOの非ブロッキング呼び出しでは、を呼び出すことで、すべてのチャネル(SocketChannel、ServerSocketChannel、FileChannelなど)を設定しますAbstractSelectableChannel.configureBlocking(false)
。ただし、これらのIO呼び出しが戻った後も、もう一度読み書きするかどうか、いつ再書き込みするかなどのチェックを制御する必要がある可能性があり
ます。たとえば、
while (!isDataEnough()) {
socketchannel.read(inputBuffer);
// do something else and then read again
}
Java 7の非同期APIを使用すると、これらのコントロールをより多様な方法で作成できます。2つの方法の1つは、を使用することCompletionHandler
です。両方のread
呼び出しが非ブロッキングであることに注意してください。
asyncsocket.read(inputBuffer, 60, TimeUnit.SECONDS /* 60 secs for timeout */,
new CompletionHandler<Integer, Object>() {
public void completed(Integer result, Object attachment) {...}
public void failed(Throwable e, Object attachment) {...}
}
}
FileChannel
は選択できず、非ブロッキングに設定できません。
多数の異なる(多くの場合は相互に排他的な)回答からわかるように、それは質問する相手によって異なります。一部のアリーナでは、用語は同義語です。または、それぞれが2つの類似した概念を参照する場合があります。
どちらの場合でも、意図は、遅いプロセスが完了するのを待ってプログラムがブロックされないようにすることです-プログラムがどのように応答することが期待されるかが唯一の真の違いです。どの用語は、プログラマーからプログラマーへ、言語から言語へ、またはプラットフォームからプラットフォームへの変更も指します。または、これらの用語は完全に異なる概念(スレッドプログラミングに関連する同期/非同期の使用など)を指す場合があります。
申し訳ありませんが、世界的に正しい正解が1つあるとは思いません。
ノンブロッキングすぐにどんなデータとのコールが戻るが用意されていますバイトの完全な数が少ない、あるいは全くなし、要求されました。
非同期呼び出しは、その全体(全体)で実行されますが、いくつかの将来の時点で完了します転送を要求します。
同期は、同時に発生すると定義されています。
非同期は、同時に発生しないものとして定義されています。
これが最初の混乱の原因です。同期は、実際には並列と呼ばれるものです。非同期はシーケンシャルですが、これを実行してから実行してください。
今、問題全体は非同期動作のモデル化に関するものです。なぜなら、開始する前に別の動作の応答を必要とする操作があるからです。したがって、これは調整の問題ですが、その操作を開始できることをどのようにして知ることができますか?
最も簡単な解決策はブロッキングとして知られています。
ブロッキングとは、他の処理が完了するのを待って、応答を返すことを選択してから、それを必要とする操作に進むことです。
したがって、トーストにバターを塗る必要がある場合、つまり、最初に繁殖した牛をトーストする必要があります。それらを調整する方法は、最初に繁殖させた牛をトーストし、トーストが飛び出るまでトースターを際限なく見つめてから、バターを塗ることに進みます。
これは最も簡単なソリューションであり、非常にうまく機能します。オペレーションとの調整を必要としない、あなたがしなければならない他のこともたまたま持っていない限り、それを使わない本当の理由はありません。たとえば、料理をする。トーストがポップするまで、トースターをじっと見つめているアイドルが、少し時間がかかることがわかっていて、完成するまで皿全体を洗えるのを待つのはなぜですか。
そこで、それぞれ非ブロッキングと非同期と呼ばれる他の2つのソリューションが登場します。
ノンブロッキングとは、操作が完了するのを待つ間、他の無関係なことを行うことを選択した場合です。必要に応じて、応答の可用性を確認してください。
トースターを見てポップする代わりに。皿全体を洗います。次に、トースターをのぞいて、トーストがポップしたかどうかを確認します。そうでない場合は、別の皿を洗い、各皿の間にあるトースターを確認します。トーストが飛び出したら、食器洗いをやめ、代わりにトーストを取り、バターを塗るようにします。
トーストを常に確認する必要があるのは面倒ですが、トースターが別の部屋にあると想像してみてください。料理の合間には、トーストを確認するために他の部屋に行く時間を無駄にします。
ここで非同期になります。
非同期とは、操作が完了するのを待つ間、他の無関係なことを行うことを選択した場合です。しかし、それをチェックする代わりに、チェックの作業を他の何かに委任し、操作自体またはウォッチャーである可能性があり、そのことを通知し、応答が利用可能になったときに通知を中断して、他の操作に進むことができますそれが必要でした。
その奇妙な用語です。これらのソリューションはすべて、依存するタスクの非同期調整を作成する方法であるため、あまり意味がありません。だからイベントと呼んでいます。
このため、トースターがアップグレードされたときにビープ音が鳴るようにトースターをアップグレードすることにしました。料理をしている間も、あなたはたえず耳を傾けています。ビープ音が聞こえたら、あなたは記憶に並んでいます。現在の皿を洗い終わったらすぐに、バターをトーストの上に置きます。または、現在の皿の洗浄を中断して、すぐにトーストを処理することもできます。
ビープ音が聞こえない場合は、パートナーにトースターを見てもらい、トーストの準備ができたときに通知してもらうことができます。パートナー自身が上記の3つの戦略のいずれかを選択して、トースターを監視し、準備ができたことを知らせるというタスクを調整できます。
最後に、非ブロッキングおよび非同期(または私がイベントと呼ぶのが好きなもの)では待機中に他のことを実行できますが、それができないことを理解するのは良いことです。ノンブロッキングコールのステータスを常にループして、他には何もしないことを選択できます。それはしばしばブロッキングよりも悪い(トースターを見て、離れて、そしてそれが完了するまでそれを戻すような)ので、多くの非ブロッキングAPIにより、ブロッキングモードに移行できます。イベントが発生した場合は、通知を受けるまでアイドル状態で待機できます。その場合の欠点は、通知の追加が複雑であり、最初からコストがかかる可能性があることです。ビープ機能付きの新しいトースターを購入するか、パートナーに説得してそれを見てもらう必要がありました。
そしてもう1つ、3つすべてが提供するトレードオフを実現する必要があります。1つは他のものより明らかに優れていません。私の例を考えてみてください。トースターの速度が速すぎると、食器を洗う時間がないため、食器洗いを開始することすらできません。これがトースターの速度です。その場合、他の何かを始めるのは時間と労力の無駄遣いに過ぎません。ブロッキングで十分です。同様に、皿を洗う場合は、トーストよりも10倍長くかかります。何を成し遂げるのがより重要であるかを自問する必要がありますか?その時までにトーストは冷たくて硬くなるかもしれませんが、それだけの価値はありません。または、待っている間、やるべきことをもっと早く選ぶべきです。もっと明確にありますが、私の答えはすでにかなり長くなっています。私のポイントは、それらすべてについて考える必要があることと、それぞれを実装してその価値があるかどうか、そしてそれが価値があるかどうかを判断する複雑さです。
編集:
これはすでに長いですが、それも完全になりたいので、さらに2つのポイントを追加します。
1)マルチプレックスと呼ばれる4番目のモデルも一般的に存在します。これは、1つのタスクを待機している間に別のタスクを開始し、両方を待機している間に次のタスクを開始する場合などです。多くのタスクがすべて開始されるまでアイドル状態で待機しますが、それら。したがって、いずれかが完了するとすぐに、その応答の処理を続行してから、他の応答を待つことに戻ることができます。多重化と呼ばれます。待機している間、各タスクを順番に確認して、完了するかどうかを確認する必要があるためです。これは、通常の非ブロッキングに加えて、少しの拡張です。
この例では、トースター、食器洗い機、電子レンジなどを起動し、それらのいずれかを待ちます。トースターをチェックして完了したかどうかを確認します。完了していない場合は、食器洗い機を確認します。完了していない場合は、電子レンジで確認します。
2)大きな間違いであると私は思いますが、同期はしばしば一度に1つのことを意味するために使用されます。そして、一度に多くの非同期。したがって、ブロッキングと非ブロッキングを指すために使用される同期ブロッキングと非ブロッキングが表示されます。また、非同期ブロッキングおよび非ブロッキングは、多重化およびイベント化を指すために使用されていました。
どうやってそこにたどり着いたのか本当にわかりません。しかし、IOと計算に関して言えば、同期および非同期は、非重複および重複としてよく知られているものを指します。つまり、非同期とは、IOと計算が重複している、つまり同時に発生していることを意味します。同期とはそうではないことを意味しますが、順次発生します。同期非ブロッキングの場合は、他のIOまたは計算を開始せず、ビジー待機してブロッキング呼び出しをシミュレートするだけです。そのような同期と非同期の誤用をやめてほしい。だから私はそれを奨励していません。
呼び出しのブロック:呼び出しが完了すると、制御が戻ります。
非ブロッキング呼び出し:制御はすぐに戻ります。その後のOSは、どういうわけか、呼び出しが完了したことをプロセスに通知します。
同期プログラム:ブロッキング呼び出しを使用するプログラム。呼び出し中にフリーズしないようにするには、2つ以上のスレッドが必要です(これが同期と呼ばれるのは、スレッドが同期して実行されているためです)。
非同期プログラム:非ブロッキング呼び出しを使用するプログラム。スレッドは1つだけですが、インタラクティブなままです。
スペルのみが異なります。彼らが何を参照しているかに違いはありません。技術的であるためには、重点が異なると言えます。非ブロッキングとは、制御フローを指します(ブロックしません。)非同期とは、event \ dataが処理されるタイミングを指します(同期ではありません)。
ブロッキング:プリミティブ(同期または非同期)の処理が完了した後、制御は呼び出しの歳差運動に戻ります
非ブロッキング:呼び出しの直後に制御がプロセスに戻ります