ベストアンサー
この質問に対する答えは、「1つのスレッド」の違いと同じです。 「」と「多く」。
しかし、おそらく実際に意味しているのは、次のようなものだと思います。単一のプロセスの単一のスレッドでのプログラミングと、単一の複数のスレッドでのプログラミングでは、プログラミング方法がどのように異なるのでしょうか。プロセス?
このトピックについての本が書かれています。しかし、ごく簡単に言えば、違いはすべて1つの要因に関連しています。単一のスレッドとプロセスでプログラミングする場合、現在の命令にどのように到達したかを常に知っています。命令は単一のシーケンスで発生します。しかし、多くのスレッドをプログラミングする場合、現在の命令に到達するためにどの命令がどの順序で実行されたかがわかりません。これにより、プログラミングがより複雑になります。
しかし、それを複雑にするもう1つの要因があります。プロセスとは異なり、スレッドはメモリを共有します。ある種の「同期」がない限り、どのスレッドが特定のメモリ位置に最後にアクセスしたか、または次にどのスレッドにアクセスするかはわかりません。したがって、Javaの「synchronized」キーワード(Adaから削除)。モニター、セマフォ、ロック、条件変数、さらにはメッセージの受け渡しもすべて同期に使用されています。
回答
(更新:シングルスレッドのWebサーバーを使用できないという別の回答に注意してください。単純に真実ではないため、同時リクエストを適切に処理します。)
マルチスレッドWebサーバーがシングルスレッドサーバーよりも優れているのはなぜですか。 そうではありません。
Webサーバーが同時実行を処理する基本的な方法は4つあります。
- フォークリクエストごとのOSプロセス(古いバージョンのApacheなど)
- リクエストごとのOSスレッドの生成(新しいバージョンのApacheなど)
- シングルスレッドのイベントループ(nginxなど)を使用)
- グリーンスレッドまたは軽量プロセスの使用OSではなくVMランタイムによってスケジュールされます(Erlangのように)
現在、最も一般的なアプローチは2番と3番です。
両方の長所と短所がありますそのうちの。 I / Oバウンド操作(一般的なWebサーバーの特性)の場合、パフォーマンスが向上します シングルスレッドイベントループを使用する場合、span>およびより多くの同時リクエスト。ただし、欠点は、すべての操作に非同期の非ブロッキングI / Oのみを使用する必要があることです。そうしないと、イベントループがブロックされ、パフォーマンスが低下します。そのため、マルチスレッドサーバーの実装は簡単ですが、パフォーマンスは高くなります。
CPUバウンド操作の場合(あまり一般的ではありません)通常のウェブサーバー。計算量の多いAPIの場合はより一般的です)、コアごとに1つのOSスレッドまたはプロセスを使用するのが最適です。コアごとに1つの複数のプロセスのクラスターを実行できるため、シングルスレッドのイベントループを使用するのは簡単です。マルチスレッドサーバーを使用するのは困難です。同時リクエストを処理する唯一の方法がスレッドの生成である場合、リクエストの数を制御しないため、スレッドの数を実際に制御することはできません。 CPUコアの数よりも多くのスレッドがあると、コンテキストスイッチのパフォーマンスが低下し、大量のRAMも使用します。
そのため、シングルスレッドのnginxサーバーは、マルチスレッドのApache Webサーバーよりもパフォーマンスが優れています(そのため、nginxが最初に作成されました)。また、 Redis は、非常に高いパフォーマンスで知られるデータベースであり、シングルスレッドです。
私があなたに与えることができる実際の例はこれです:私の最初のウェブサーバーは500MBのRAMを備えたLinuxマシン上で実行されているApacheでした。リクエストごとに新しいプロセスをフォークしました(実際にはプールがあったため、フォークはそれほど多くありませんでしたが、リソースリークを回避するために、プロセスを再利用してときどき強制終了するために、これらのプロセスを存続させる必要がありました)。
私のOSは約100MBのRAMを使用していました。すべてのApacheプロセスは20MBのRAMを使用しました。つまり、サーバーは20の同時リクエストしか処理できず、RAMがなくなったため、それを回避する方法はありませんでした。プロセスはほとんどI / Oでブロックされていたため、CPU使用率は非常に低く、20を超えるすべての要求は待機する必要があり、20がダウンロードが長時間実行されると、サーバーが完全に応答しなくなりました。
nginx Webサーバーが導入されたとき、シングルスレッドのイベントループを使用し、リクエストをブロックしませんでした。神話上のc10k問題に問題なく、はるかに多くの同時リクエストを処理できます。nginxは基本的にc10k問題(10,000の同時リクエスト)を解決するために作成されました。
10,000スレッドで無駄になるRAMの量を想像してみてください。コンテキストスイッチに使用される時間とその数を生成することさえできます。
マルチスレッドApacheとシングルスレッドnginxのメモリ使用量:
ちなみに、これがRyanDahlがNode.jsでノンブロッキングI / Oとシングルスレッドイベントループを使用し、Denoでも同じアイデアを使用している理由です。 これが高性能ネットワークサーバーを作成する方法だからです(他の回答で読んだものとは異なります)。