なぜグリーンスレッドではないのですか?


33

私はこれに関する質問がすでにカバーされていることを知っていますが(例えばhttps://stackoverflow.com/questions/5713142/green-threads-vs-non-green-threads)、満足のいく答えが得られたとは感じません。

問題は、なぜJVMがグリーンスレッドをサポートしないのかということです。

コードスタイルのJava FAQでこれを言っています

緑のスレッドは、すべてのコードが単一のオペレーティングシステムスレッドで実行されるJava仮想マシン(JVM)の動作モードを指します。

そして、これはjava.sun.com上で

欠点は、グリーンスレッドを使用すると、Linuxのシステムスレッドが利用されないため、CPUを追加してもJava仮想マシンがスケーラブルではないことです。

JVMには、コアの数に等しいシステムプロセスのプールがあり、その上でグリーンスレッドを実行できるように思えます。頻繁にブロックする非常に多くのスレッドがある場合、これはいくつかの大きな利点を提供します(主に現在のJVMがスレッド数を制限するため)。

考え?


5
私には、なぜグリーンスレッドなのかという疑問があります。複数のプロセスを介してJVMレベルでそれをエミュレートすることにより、マルチスレッドを再導入するのはなぜですか?スレッドを生成することでプログラマがより寛大になることを許可する以外に、一見利益がないようにするための多くの苦痛とオーバーヘッドです(そして、私はそれが利点だと確信していません)。

4
まあ、それはスケーリングする並行プログラミングモデルを持つことです。現在、Javaでは、スケーラビリティが必要な場合は、独自のスレッドプールでNIOに切り替えます。少なくとも、それは私の理解です。
redjamjar

3
軽量スレッドをサポートする< akka.io >のようなものが存在することも、必要があると思います。実際には、単に<ここでかなり良い議論を見つけたstackoverflow.com/questions/7458782/... >
redjamjar

2
@delnanネイティブスレッドのコンテキストスイッチのコストのため。緑色のスレッドは、コンテキスト切り替えとプロセス間同期のオーバーヘッドがはるかに少ないです。さらに、グリーンスレッドの量は事実上無制限です(VMプロセスに過度のストレスをかけずに数十万個にすることができます)が、ネイティブスレッドの量はOSとメモリオーバーヘッドによって制限されます。
-permeakra

JVMがネイティブスレッドを直接サポートするまでに時間がかかりました。それまでは、グリーンスレッドが中間的な解決策でした。
トールビョーンラウンアンデルセン

回答:


29

JVMがグリーンスレッドを放棄し、ネイティブスレッドに移行したことを覚えています。これは2つの単純な理由によるものです。グリーンスレッドは率直に言ってごみであり、Sunで利用できる開発者の努力は限られていますが、マルチコアプロセッサをサポートする必要がありました。

これは残念なことでした-緑のスレッドはより優れた抽象化を提供し、並行性を障害物ではなく有用なツールにすることができます。しかし、いくつかのハードルを克服できない場合、緑色のスレッドは役に立ちません。

  • 利用可能なすべてのCPUコアを使用する必要があります

  • コンテキスト切り替えは安価でなければなりません

  • I / Oは、いずれかのスレッドがそれに従事しますが、ブロックすることがありませんいくつかの初期の実装ではそうであった他のすべてのスレッドを、他のスレッドが確かではありません。

Javaでマルチスレッド化がなぜ難しいのかとよく疑問に思っていましたが、今では明らかになっています。最終的にはネイティブスレッドへの切り替えに関係していました。

  • すべてのCPUコアの使用が得意

  • 独立したI / Oなどを提供する、真の並行性が得意

  • コンテキストの切り替えが遅い(最適なグリーンスレッドの実装と比較して)

  • 恐ろしくメモリに貪欲であるため、それらの最大使用可能数を制限します

  • 現実の世界を表現するためのあらゆる基盤に対する貧弱な抽象化であり、もちろん非常に同時的です。

最近では、プログラマーの多くの時間は、ノンブロッキングI / Oや先物などのコーディングに費やされています。これは、より優れた抽象化レベルを持たない大きな恥です。

比較のために、Erlangのほかに、新しいGo言語は非常に大きな並行性を発揮します。それらの祖父はすべてOccamのままであり、まだ進行中の研究プロジェクトです。


あなたが投稿した時からどのくらい行きましたか:O
Dmitry

3
残念ながら、Rustはより良い並行性抽象化を放棄した別の言語です。彼らも協力的なスレッドからネイティブスレッドに移行することを決めました。
リック777

2
@ Rick-777 Rustは低レベルすぎてそれができません。
マルコム

15

複数のスレッドを偽装する単一のプロセスには、多くの問題があります。その1つは、偽のスレッドがすべてページフォールトで停止することです。

提案するプロセスプールの選択肢には、いくつかの利点と欠点があります。最大の利点である「スレッド」の分離は、実際にはここではあまり得られません。大きな不利な点、実装の極端な難しさと同期の効率の悪さは、ここでの取り決めです。

ただし、スレッドのプールのように使用できるプロセスのプール(Java以外)が存在する(ただし、より分離されている)アプリケーションが存在するのは素晴らしいことです。スレッドはほとんどすべてを共有します。プロセスを使用すると、共有するものを具体的に選択できます。私の知る限り、誰もまだそれを実装する努力をしていません。


Occamはこれを提供すると主張しています。80年代には重要な言語でしたが、開発資金が不足していたため、研究のニッチのみになりました。しかし、並行性に関するそのアイデアは、当時と同じくらい堅実であり、まだ改善されていません。
リック-777 14

あなたが「マルチスレッド」を使用している場合(「M:N」タイプのスケジューリング)、理論的には他のスレッドが「たるみを拾う」(他の緑のスレッド)ことができるため、ページフォールトによってブロックされるのは1つの緑のスレッドだけです。 ... softwareengineering.stackexchange.com/questions/222642/...
rogerdpack

13

平均的なJavaコードにはまったくメリットはありません。JavaはErlangではなく、JavaプログラマーはErlangプログラマーと同じ考え方ではありません。この言語をこのように使用することは意図されていませんでした。

真の軽量プロセスが必要な場合-Erlangを使用して、メッセージを介して通信する数千のスレッドを作成します。Javaでは、ミューテックスとセマフォと共通のメモリを共有する多数のスレッドがあります。これは、さまざまな問題に対応するために設計された単なるプログラミングモデルです。


したがって、明確にするために、これはErlangでの有用なアプローチです。そして、Javaの考え方の問題を無視すると、実際に役立つでしょうか?
redjamjar

1
@ redjamjar、Javaでは有用ではない可能性があり、言語自体はそのような使用にはあまり適しておらず、その主な(そして唯一の)利点-すぐに使用できるライブラリの広大なボディ-このようなエイリアンにはうまく適合しませんプログラミングアプローチ。
SKロジック

ええ、そのモデルが必要な場合は、アーランを使用するだけで、桁違いに簡単になります
ザカリーK

1
Java!= JVM、ちょうど言って:)
カミルトムシク

1
@Bane、これらの「利点は、」のみ比較するあなたが持っている場合は何も存在しない
SK-ロジック
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.