web-dev-qa-db-ja.com

非同期と非ブロッキング

非同期呼び出しと非ブロッキング呼び出しの違いは何ですか?また、ブロッキング呼び出しと同期呼び出しの間で(例を挙げてください)?

336
user331561

多くの場合、それらは同じものの異なる名前ですが、状況によってはまったく異なります。依存します。用語は、ソフトウェア業界全体に完全に一貫した方法で適用されるわけではありません。

たとえば、クラシックソケットAPIの場合、非ブロッキングソケットは、特別な「ブロックする」エラーメッセージでただちに戻るのに対し、ブロッキングソケットはブロックします。再試行するのに適したタイミングを見つけるには、selectpollなどの別の関数を使用する必要があります。

ただし、非同期ソケット(Windowsソケットでサポートされている)、または.NETで使用される非同期IOパターンの方が便利です。メソッドを呼び出して操作を開始すると、フレームワークは完了時にコールバックします。ここでも、基本的な違いがあります。非同期Win32ソケットは、ウィンドウメッセージを渡すことで特定のGUIスレッドに結果を「マーシャリング」しますが、.NET非同期IOはフリースレッドです(コールバックがどのスレッドで呼び出されるかわかりません)。

したがって、必ずしも同じことを意味するわけではありません。ソケットの例を特定するには、次のようにします。

  • ブロッキングと同期は同じことを意味します。APIを呼び出すと、何らかの答えが得られるまでスレッドがハングアップして返されます。
  • ノンブロッキングとは、回答を迅速に返せない場合、APIがエラーを返し、すぐに返ってそれ以外のことは何もしないことを意味します。そのため、APIを呼び出す準備ができているかどうかを照会する(つまり、効率的な方法で待機をシミュレートし、タイトループでの手動ポーリングを回避する)ための関連する方法が必要です。
  • 非同期とは、リクエストを実行するための「バックグラウンド」の努力を開始して、APIが常に即座に戻ることを意味するため、結果を取得するための関連する方法が必要です。
275
  • 非同期は実行された何かを指します並列は、別のスレッドであると言います。
  • 非ブロッキングは、多くの場合ポーリングを指します。つまり、指定された条件が保持されているかどうかを確認します(ソケットが読み取り可能である、デバイスにデータがあるなど)。
44

同期/非同期は、2つのモジュール間の関係を記述することです。
ブロッキング/ノンブロッキングは、1つのモジュールの状況を記述することです。

例:
モジュールX:「I」。
モジュールY:「本屋」。
XがYに尋ねる:「c ++ primer」という本がありますか?

1)ブロック:YがXに答える前に、Xはそこで答えを待っています。これで、X(1つのモジュール)がブロックされます。 XとYは2つのスレッドまたは2つのプロセスですか、1つのスレッドまたは1つのプロセスですか?わからない。

2)ノンブロッキング:YがXに答える前に、Xはそこを離れ、他のことをします。 Xは2分ごとに戻って、Yが仕事を終えたかどうかを確認しますか?または、Yは彼に電話するまでXは戻ってきませんか?わからない。Yが仕事を終える前にXが他のことをできることだけを知っている。ここで、X(1つのモジュール)は非ブロッキングです。 XとYは2つのスレッドまたは2つのプロセスまたは1つのプロセスですか?わからない。ただし、XとYを1つのスレッドにすることはできません。

3)同期:YはXに応答する前に、Xはそこで応答を待機し続けます。これは、Yがジョブを完了するまでXが続行できないことを意味します。次に、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はループから飛び出すことはできません)。
通常、この場合、非ブロッキングは愚かなループに多くのリソースを費やすため、make 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は非ブロッキングです
  • X1とX2は同期しています
  • XとYは非同期です

必要に応じて、X1で作成されたスレッドを4つの単語で説明することもできます。

より重要なことは、非同期ではなく同期をいつ使用するかです。非ブロッキングの代わりにブロッキングを使用するのはいつですか?

Nginxが非ブロッキングなのはなぜですか? Apacheがブロックしているのはなぜですか?

適切な選択を行うには、ニーズを分析し、さまざまなアーキテクチャのパフォーマンスをテストする必要があります。さまざまなニーズに適したアーキテクチャはありません。

34
Yves

この質問をJava 7のNIOおよびNIO.2のコンテキストに入れると、非同期IOはノンブロッキングよりも一歩進んだものになります。 Java NIOノンブロッキング呼び出しでは、AbstractSelectableChannel.configureBlocking(false)を呼び出すことにより、すべてのチャネル(SocketChannel、ServerSocketChannel、FileChannelなど)をそのように設定します。ただし、これらの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) {...}
    }
}
15
Anthony

おそらく多くの異なる(そしてしばしば相互に排他的な)答えからわかるように、それはあなたが尋ねる人に依存します。一部のアリーナでは、用語は同義語です。または、それぞれ2つの類似した概念を参照する場合があります。

  • 1つの解釈は、制御する必要のない長いプロセスによってプログラムが滞らないようにするために、呼び出しは基本的に監視なしでバックグラウンドで何かを行うというものです。オーディオの再生は一例かもしれません-プログラムが関数を呼び出して(たとえば)mp3を再生し、その時点から他のことを続けながらOSに任せて、サウンドハードウェアでオーディオをレンダリングするプロセスを管理できます。
  • 別の解釈は、呼び出しはプログラムが監視する必要があることを行いますが、プロセスの重要なポイントでプログラムに通知するだけで、ほとんどのプロセスがバックグラウンドで発生することを許可します。たとえば、非同期ファイルIOは一例です。プログラムはファイルに書き込むためにオペレーティングシステムにバッファを提供し、OSは操作が完了するかエラーが発生したときにのみプログラムに通知します。

いずれの場合も、遅いプロセスが完了するのを待ってプログラムがブロックされないようにすることが目的です-プログラムの応答方法が唯一の本当の違いです。どの用語は、プログラマからプログラマへ、言語から言語へ、またはプラットフォームからプラットフォームへも変化します。または、これらの用語は完全に異なる概念(スレッドプログラミングに関連する同期/非同期の使用など)を指す場合があります。

申し訳ありませんが、世界的に正しい単一の正しい答えがあるとは思いません。

15
Mac

nonblocking呼び出しは、利用可能なデータ(要求されたバイトの全数、少ない、またはまったくない)を即座に返します。

非同期呼び出しは、全体(全体)で実行される転送を要求しますが、将来のある時点で完了します。

12
Koray Tugay

ノンブロッキング:この関数はスタック上で待機しません。

非同期:関数呼び出しがスタックを離れた後、関数呼び出しに代わって作業を続行できます

9

同期は同時に発生すると定義されています。

非同期は同時に発生しないと定義されています。

これが最初の混乱の原因です。同期は、実際には並列と呼ばれるものです。非同期はシーケンシャルですが、これを実行してから実行してください。

さて、全体の問題は非同期の振る舞いをモデル化することです。なぜなら、開始する前に別の応答を必要とする操作があるからです。したがって、これは調整の問題です。その操作を開始できることをどのように知るのでしょうか。

最も簡単な解決策はブロッキングとして知られています。

Blockingは、必要な操作に進む前に、他のことが行われるのを待って応答を返すことを選択した場合です。

したがって、バターをトーストにかける必要があり、したがって、最初に品種をトーストする必要がある場合。それらを調整する方法は、最初に品種をトーストし、トースターが飛び出るまでトースターを際限なく凝視し、次にそれらにバターをかけることです。

これは最も簡単なソリューションであり、非常にうまく機能します。運用との調整を必要としない他の作業が必要な場合を除き、使用しない本当の理由はありません。たとえば、いくつかの料理をします。トーストが鳴るのに少し時間がかかることがわかっているのに、トースターをじっと見つめているのを待つのはなぜですか?

そこで、それぞれノンブロッキングと非同期として知られる他の2つのソリューションが登場します。

非ブロッキングは、操作が完了するのを待っている間に他の無関係なことを行うことを選択した場合です。適切と思われる応答の可用性を確認してください。

そのため、トースターを見てポップするのではなく。あなたは行って、皿全体を洗います。そして、トースターが覗いているかどうかを確認するためにトースターを覗きます。そうでない場合は、別の皿を洗い、各皿の間にあるトースターで確認します。トーストがぽんと鳴ったら、皿の洗浄をやめ、代わりにトーストを取り、バターをかけます。

トーストを常にチェックしなければならないのは面倒です。トースターが別の部屋にあると想像してください。料理の合間に、他の部屋に行ってトーストをチェックする時間を無駄にします。

これは非同期です。

非同期は、操作の完了を待っている間に他の無関係なことを行うことを選択した場合です。ただし、確認する代わりに、確認作業を他の何かに委任します。操作自体またはウォッチャーである可能性があり、そのことを通知し、応答が利用可能になったときに割り込む可能性があるため、他の操作に進むことができますそれが必要でした。

その奇妙な用語。これらのソリューションはすべて、依存タスクの非同期調整を作成する方法であるため、あまり意味がありません。だから私はそれをイベントと呼ぶことを好みます。

このため、トースターが完了するとビープ音が鳴るようにトースターをアップグレードすることにしました。料理をしているときでも、常に耳を傾けています。ビープ音が聞こえたら、現在の皿を洗い終わったらすぐに立ち止まってトーストにバターを塗ります。または、現在の皿の洗浄を中断し、すぐにトーストを処理することもできます。

ビープ音が聞こえない場合は、パートナーにトースターを見てもらい、トーストの準備ができたら教えてください。パートナーは、上記の3つの戦略のいずれかを選択して、トースターを見て、準備ができたときに通知するというタスクを調整できます。

最後に、非ブロッキングと非同期(またはイベントと呼んでいるもの)を使用すると、待機中に他のことを行うことができますが、あまり持っていないことを理解しておくことをお勧めします。ノンブロッキングコールのステータスを常にチェックし、他に何もせずにループすることを選択できます。しかし、それはブロッキングよりも悪いことが多い(トースターを見てから離れて、それが終わるまで戻る)ので、多くのノンブロッキングAPIからブロッキングモードに移行することができます。イベントが発生した場合は、通知されるまでアイドル状態で待つことができます。その場合のマイナス面は、通知の追加が複雑で、最初はコストがかかる可能性があることです。ビープ機能付きの新しいトースターを購入するか、パートナーにそれを見てもらうよう説得する必要がありました。

そしてもう1つ、3つすべてが提供するトレードオフを実現する必要があります。 1つは明らかに他のものより優れていません。私の例を考えてください。トースターが非常に高速である場合、皿を洗う時間がなく、洗うことさえ始められません。トースターがどれほど速いかです。その場合、他の何かを始めるのは時間と労力の無駄です。ブロッキングは行います。同様に、皿を洗うのにトーストの10倍の時間がかかる場合。何をするのがより重要かを自問する必要がありますか?その時間までにトーストは冷たくて硬くなるかもしれませんが、それだけの価値はありません。または、待機中に実行するより高速なものを選択する必要があります。もっと明らかにありますが、私の答えはすでにかなり長いです、私のポイントは、あなたはそれすべて、そしてそれを価値があるかどうか、それが実際にあなたの全体またはパフォーマンスを改善するかどうかを決定するためにそれぞれを実装する複雑さを考える必要があるということです。

編集:

これはすでに長いですが、完成させたいので、さらに2点追加します。

1)多重化として知られる4番目のモデルも一般的に存在します。これは、1つのタスクを待っている間に別のタスクを開始し、両方を待っている間にもう1つのタスクを開始する、というように、すべてのタスクがすべて開始されてから、アイドル状態になりますが、それら。そのため、いずれかが完了するとすぐに、その応答の処理に進み、その後、他の応答を待つことに戻ることができます。待機中は、各タスクを順番にチェックして、それらが完了するまで、完了したかどうかを確認する必要があるため、多重化と呼ばれます。通常のノンブロッキングに加えて、少し拡張されています。

この例では、トースターを開始し、次に食器洗い機、電子レンジなどを起動して、それらのいずれかを待機するようなものです。トースターをチェックして、完了したかどうかを確認します。完了していない場合は、食器洗い機をチェックし、そうでない場合は、電子レンジをチェックします。

2)それは大きな間違いだと思いますが、同期は一度に1つのことを意味するためによく使用されます。そして、一度に多くの非同期を行います。したがって、ブロッキングとノンブロッキングを参照するために使用される同期ブロッキングと非ブロッキングが表示されます。また、非同期ブロッキングと非ブロッキングは、多重化されたイベントを指すために使用されます。

どうやってそこにたどり着いたのか本当に分かりません。しかし、IOおよび計算に関しては、同期および非同期はしばしば、非オーバーラップおよびオーバーラップとして知られるものを指します。つまり、非同期とは、IOと計算が重複することを意味します。同期は、そうではないことを意味します。したがって、順次発生します。同期非ブロッキングの場合、他のIOまたは計算を開始せず、ただ待機してビ​​ジー状態にし、ブロッキングコールをシミュレートします。人々がそのような同期的および非同期的な誤用をやめることを願っています。だから私はそれを奨励していません。

4
Didier A.

ブロック呼び出し:呼び出しが完了すると制御が戻ります。

非ブロッキング call:制御はすぐに戻ります。後でOSが何らかの形でプロセスに呼び出しが完了したことを通知します。


同期プログラム:Blocking呼び出しを使用するプログラム。呼び出し中にフリーズしないようにするには、2つ以上のスレッドが必要です(そのため、同期と呼ばれます-スレッドは同期的に実行されています)。

非同期プログラム:非ブロッキング呼び出しを使用するプログラム。スレッドは1つだけであり、対話型のままです。

2

スペルのみが異なります。それらが参照するものに違いはありません。技術的には、強調が異なると言えます。非ブロックとは、制御フローを指します(ブロックしません。)非同期とは、イベント\データが処理されるときを指します(同期ではありません)。

0
stonemetal

ブロックモデルでは、開始アプリケーションがI/Oの開始時にブロックする必要があります。つまり、処理とI/Oを同時にオーバーラップすることはできません。同期ノンブロッキングモデルでは、処理とI/Oのオーバーラップが可能ですが、アプリケーションがI/Oのステータスを定期的にチェックする必要があります。これにより、非同期の非ブロッキングI/Oが残り、I/O完了の通知を含む処理とI/Oのオーバーラップが可能になります。

0
P.Gurung