非同期と非ブロッキング


373

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



1
私は本<Unix Networking Programming> Col 1、Chapter 6
Bin

2
興味深い記事:非同期I / Oを使用してアプリケーションのパフォーマンスを向上させる。I / Oパラダイムは、(1)ブロッキング+同期、(2)ノンブロッキング+同期、(3)ブロッキング+非同期、(4)ノンブロッキング+非同期の4つのカテゴリに分類されます。
MS Dousti 2017

@MSDousti Googleの専門家から、これはいくつかの点で間違っていると言われました。
Rick、

@MSDoustiいくつかの調査の後、コメントで説明したように、(3)と(2)の組み合わせはないと思います。非同期の定義を確認してください。これは、非ブロッキングと同じことについて話しています。上の答えを見るとわかるように、それは私の意見を裏付けるものです。ポーリングとコールバック関数は、非同期を実装するための単なる方法/パターンです。はい、私はブロッキング、同期、および非ブロッキング、非同期が同義語の2つのペアであることを言っています。
リック、

回答:


304

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

たとえば、クラシックソケットAPIでは、非ブロッキングソケットは、特別な「ブロックする」というエラーメッセージが表示されてすぐに戻るソケットですが、ブロッキングソケットはブロックします。selectまたはなどの別の関数を使用する必要がありますpollいつ再試行するのが適切を確認するがあります。

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

したがって、それらは常に同じことを意味するわけではありません。ソケットの例を詳しく説明すると、次のようになります。

  • ブロッキングと同期は同じことを意味します。APIを呼び出すと、なんらかの応答が返されて返されるまでスレッドがハングアップします。
  • ノンブロッキングとは、回答を迅速に返すことができない場合、APIはエラーですぐに戻り、それ以外は何もしないことを意味します。したがって、APIを呼び出す準備ができているかどうかを照会する関連する方法がいくつかあります(つまり、タイトループでの手動ポーリングを回避するために、効率的な方法で待機をシミュレートするため)。
  • 非同期とは、APIが常にすぐに戻り、リクエストを満たすための「バックグラウンド」作業を開始したことを意味します。そのため、結果を取得するためのいくつかの関連する方法が必要です。

完了状態IOではなく、準備状態IO。Linux上でlibaioを見る
ウィル

4
これらの用語は状況依存であり、一貫性のない使用が行われる場合があることを指摘していただきありがとうございます。私は特にテクノロジーに気づきますが、他の分野でも、その事実を認めた方が、正確な定義が正しいかどうかについて議論するよりも、時々発生するように、その方が便利なことがよくあります。
チャドNB

2
フォローアップQ:答えは、用語間に2つの異なる区別をするようです。まず、通知:ノンブロッキングは、アプリケーションが後で再度チェックする必要があることを意味します(ポーリング)。第2に、アクション:ノンブロッキングはエラーを返す以外に何もしませんが、非同期はアクションをキューに入れるか、ある意味「バックグラウンドで」実行します。用語を区別する上でどの違いがより重要ですか?どちらの区別も1つの用語に強く関連していますか?それともあいまいですか?
チャドNB

2
@ChadNB-用語として、非ブロッキングはポーリングと強く関連しています。APIがあなたの呼び出しを「記憶」しているかどうかの質問について:APIが記憶する唯一の理由は、あなたに電話をかけるためです。再ポーリングするためにそれを呼び出す場合は、後続の呼び出しを行うために必要な状態を維持する必要があります。そのため、APIは状態を維持しても値を追加しません。
Daniel Earwicker

6
ノンブロッキングコールは「エラー」を返すと言うよりは、ノンブロッキングコールが本質的に即座に実行できる限りのことを行い、それがどれだけ行われたかを示す方が正確だと思います。一部の操作では、実行される作業量は「すべて」または「なし」のいずれかになりますが、他の一部の操作(ストリームI / Oなど)は定量的な指標を返す場合があります。非ブロッキングは、意味的には、ブロッキングI / O実装でタイムアウトになる操作を後でスムーズに再試行できる場合(非常に短い場合もあればそうでない場合もある)、タイムアウトが非常に短いブロッキングと同等です。
スーパーキャット2014

56

同期/非同期は、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は非ブロッキングです
  • X1とX2は同期です
  • XとYは非同期です

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

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

Nginxが非ブロッキングになるのはなぜですか?Apacheがブロックされるのはなぜですか?

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


7
IMOは、1つまたは2つの参加者間の関係という概念の本質を捉えるため、最良の回答です。
ファビオ2018

1と3の両方で、YはLIMITEDリソースとして機能しています。Xを助けるYはもういません
UVM

46
  • 非同期とは、別のスレッドなど、並行して実行れるものを指します。
  • 非ブロッキングとは、多くの場合、ポーリング、つまり特定の条件が満たされているかどうかを確認することを意味します(ソケットが読み取り可能である、デバイスにさらに多くのデータがあるなど)。

17
I / Oが関係する場合、非同期は通常「並列」でも「別のスレッド」でもありません。ほとんどが通知ベースです。つまり、ブロックせず、ポーリングせず、信号を取得するだけです。もちろん、信号は「別のスレッド」と考えることができる「現実の世界」から来ていると主張することができます...
ハビエル

ええ、はい、私たちは一日中正確な表現を議論できます:)
Nikolai Fetissov 2010

しかし、LinuxのAIOをどのように説明しますか?非同期と非ブロッキングの両方を使用しています。AIO LINKS
Djvu

16
この答えを読んでいる人には、これは正確な言葉遣いについて議論しているのではありません。並行性と並列性が同じ概念ではないのと同じように、それらを区別することは言葉遣いの問題ではありません。非同期性と並列性は2つの異なる野獣であり、この答えはそれらを不正確に同じものにします。
Ptival 16

2
非同期は、必ずしも並列で行われることを意味するわけではありません。同時および並列プログラミングに関するスタックオーバーフローに関するこの素晴らしい投稿を参照してください。
BARJ 2017年

17

この質問を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) {...}
    }
}

3
FileChannelは選択できず、非ブロッキングに設定できません。
michaelliu 2014年

15

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

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

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

申し訳ありませんが、世界的に正しい正解が1つあるとは思いません。


1
+1良い答え。「非同期」とは非ブロッキングまたは Microsoft非同期(イベントベース/コールバック)アプローチのいずれかを意味する可能性があることを人々は認識する必要があります。
エンジニア

14

ノンブロッキングすぐにどんなデータとのコールが戻るが用意されていますバイトの完全な数が少ない、あるいは全くなし、要求されました。

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


ノンブロッキングは何も結果を返さない
アパルティコのCEO

9

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

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


1
@Marenzは、posix呼び出しで非ブロッキングioを直接実行できないことを意味します。それは彼がここで与える意味を変えません。
tmc

@Marenzこれは、フラグがファイルに対して無視されることを意味します。この回答の意味には影響しません。
ローン侯爵

8

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

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

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

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

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

ブロッキングとは、他の処理が完了するのを待って、応答を返すことを選択してから、それを必要とする操作に進むことです。

したがって、トーストにバターを塗る必要がある場合、つまり、最初に繁殖した牛をトーストする必要があります。それらを調整する方法は、最初に繁殖させた牛をトーストし、トーストが飛び出るまでトースターを際限なく見つめてから、バターを塗ることに進みます。

これは最も簡単なソリューションであり、非常にうまく機能します。オペレーションとの調整を必要としない、あなたがしなければならない他のこともたまたま持っていない限り、それを使わない本当の理由はありません。たとえば、料理をする。トーストがポップするまで、トースターをじっと見つめているアイドルが、少し時間がかかることがわかっていて、完成するまで皿全体を洗えるのを待つのはなぜですか。

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

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

トースターを見てポップする代わりに。皿全体を洗います。次に、トースターをのぞいて、トーストがポップしたかどうかを確認します。そうでない場合は、別の皿を洗い、各皿の間にあるトースターを確認します。トーストが飛び出したら、食器洗いをやめ、代わりにトーストを取り、バターを塗るようにします。

トーストを常に確認する必要があるのは面倒ですが、トースターが別の部屋にあると想像してみてください。料理の合間には、トーストを確認するために他の部屋に行く時間を無駄にします。

ここで非同期になります。

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

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

このため、トースターがアップグレードされたときにビープ音が鳴るようにトースターをアップグレードすることにしました。料理をしている間も、あなたはたえず耳を傾けています。ビープ音が聞こえたら、あなたは記憶に並んでいます。現在の皿を洗い終わったらすぐに、バターをトーストの上に置きます。または、現在の皿の洗浄を中断して、すぐにトーストを処理することもできます。

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

最後に、非ブロッキングおよび非同期(または私がイベントと呼ぶのが好きなもの)では待機中に他のことを実行できますが、それができないことを理解するのは良いことです。ノンブロッキングコールのステータスを常にループして、他には何もしないことを選択できます。それはしばしばブロッキングよりも悪い(トースターを見て、離れて、そしてそれが完了するまでそれを戻すような)ので、多くの非ブロッキングAPIにより、ブロッキングモードに移行できます。イベントが発生した場合は、通知を受けるまでアイドル状態で待機できます。その場合の欠点は、通知の追加が複雑であり、最初からコストがかかる可能性があることです。ビープ機能付きの新しいトースターを購入するか、パートナーに説得してそれを見てもらう必要がありました。

そしてもう1つ、3つすべてが提供するトレードオフを実現する必要があります。1つは他のものより明らかに優れていません。私の例を考えてみてください。トースターの速度が速すぎると、食器を洗う時間がないため、食器洗いを開始することすらできません。これがトースターの速度です。その場合、他の何かを始めるのは時間と労力の無駄遣いに過ぎません。ブロッキングで十分です。同様に、皿を洗う場合は、トーストよりも10倍長くかかります。何を成し遂げるのがより重要であるかを自問する必要がありますか?その時までにトーストは冷たくて硬くなるかもしれませんが、それだけの価値はありません。または、待っている間、やるべきことをもっと早く選ぶべきです。もっと明確にありますが、私の答えはすでにかなり長くなっています。私のポイントは、それらすべてについて考える必要があることと、それぞれを実装してその価値があるかどうか、そしてそれが価値があるかどうかを判断する複雑さです。

編集:

これはすでに長いですが、それも完全になりたいので、さらに2つのポイントを追加します。

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

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

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

どうやってそこにたどり着いたのか本当にわかりません。しかし、IOと計算に関して言えば、同期および非同期は、非重複および重複としてよく知られているものを指します。つまり、非同期とは、IOと計算が重複している、つまり同時に発生していることを意味します。同期とはそうではないことを意味しますが、順次発生します。同期非ブロッキングの場合は、他のIOまたは計算を開始せず、ビジー待機してブロッキング呼び出しをシミュレートするだけです。そのような同期と非同期の誤用をやめてほしい。だから私はそれを奨励していません。


「同期は同時に発生していると定義されている」と言った理由がわかりませんか?全体の考えは、それは同時ではない、つまり同時に起こっていないということです。
ヘルシング

それは素晴らしいアナロジーでした!乾杯しました!
d-coder、

@Helsingそれが文字通りの意味です。同期は同じ時間を意味し、非同期は同じ時間ではないことを意味します:p。何かが非同期である理由は、それが同時に起こることはあり得ないので、それは前または後に起こる必要があります。同時に発生する可能性がある場合は、単純に並列化するか、任意の順序で実行することができ、明示的な同期は必要ありません。それが非同期プログラミングがこれを行うことのすべてである理由であり、それから、これらのことを待ってから、など。
Didier A.

@Helsingまた、並行は並列と同じではありません。2つのことが同時に発生しているという意味ではなく、いずれかが完了する前に1つ以上のものが進行していることを意味します。これは、並列化、または単にインターリーブ、つまりタスク切り替えで実現できます。
Didier A.

4

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

非ブロッキング呼び出し:制御はすぐに戻ります。その後のOSは、どういうわけか、呼び出しが完了したことをプロセスに通知します。


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

非同期プログラム:非ブロッキング呼び出しを使用するプログラム。スレッドは1つだけですが、インタラクティブなままです。


1
非ブロッキング呼び出し:制御は、基本的にすぐに実行できる限りのことを行った後に戻ります。メソッドは、どれだけのことが行われたかを示します。これは、呼び出しのブロックについて説明したとおりに動作する非同期呼び出しとは異なります。
スーパーキャット2014

0

スペルのみが異なります。彼らが何を参照しているかに違いはありません。技術的であるためには、重点が異なると言えます。非ブロッキングとは、制御フローを指します(ブロックしません。)非同期とは、event \ dataが処理されるタイミングを指します(同期ではありません)。


0

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


-2

ブロッキング:プリミティブ(同期または非同期)の処理が完了した後、制御は呼び出しの歳差運動に戻ります

非ブロッキング:呼び出しの直後に制御がプロセスに戻ります


10
これは、尋ねられていることに答えることさえしません。
Koray Tugay
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.