私はただのGoユーザーであるため、次のことを一言で言ってください。
ウィキペディアでは、グリーンスレッドを「基礎となるオペレーティングシステムではなく、仮想マシン(VM)によってスケジュールされるスレッド」と定義しています。グリーンスレッドは、ネイティブOS機能に依存せずにマルチスレッド環境をエミュレートし、カーネルスペースではなくユーザースペースで管理されるため、ネイティブスレッドをサポートしていない環境で動作できます。
Go(または正確には2つの既存の実装)は、ネイティブコードのみを生成する言語です。VMは使用しません。さらに、現在のランタイム実装のスケジューラーは、OSレベルのスレッドに依存しています(GOMAXPROCS = 1の場合でも)。したがって、Goモデルのグリーンスレッドについて話すのは少し虐待的だと思います。
Goの人々は、特に他の同時実行メカニズム(コルーチンやスレッド、軽量プロセスなど)との混同を避けるためにゴルーチンの用語を作成しました。
もちろん、GoはM:Nスレッドモデルをサポートしていますが、JavaグリーンスレッドモデルよりもErlangプロセスモデルに非常に近いように見えます。
グリーンスレッド(初期のJVMに実装されている)に対するGoモデルの利点を次に示します。
開発者にとって透過的な方法で、複数のコアまたはCPUを効果的に使用できます。Goを使用すると、開発者は並行性に注意する必要があります。Goランタイムは並列処理を行います。Javaグリーンスレッドの実装は、複数のコアやCPUにまたがってスケールしませんでした。
システムコールとCコールは、スケジューラに対してブロックされません(イベントループで多重化されたI / Oをサポートするコールだけでなく、すべてのシステムコール)。グリーンスレッドの実装は、ブロッキングシステムコールが行われたときにプロセス全体をブロックできました。
スタックのコピーまたはセグメント化。Goでは、ゴルーチンの最大スタックサイズを指定する必要はありません。スタックは必要に応じて徐々に大きくなります。その結果、ゴルーチンは多くのメモリ(4KB〜8KB)を必要としないため、大量のメモリを喜んで生成できます。したがって、ゴルーチンの使用は広範囲に及ぶ可能性があります。
今、批判に対処するために:
Goを使用すると、ユーザースペーススケジューラを作成する必要はありません。ランタイムに既に提供されています。複雑なソフトウェアですが、Goユーザーの問題ではなく、Go開発者の問題です。その使用法はGoユーザーには透過的です。Go開発者の中で、Dmitri Vyukovはロックフリー/ウェイトフリープログラミングの専門家であり、スケジューラの最終的なパフォーマンスの問題に対処することに特に興味があるようです。現在のスケジューラの実装は完全ではありませんが、改善されます。
同期はパフォーマンスの問題と複雑さをもたらします。これはGoでも部分的に当てはまります。ただし、Goモデルは、チャネルの使用と並行ゴルーチンでのプログラムの完全な分解を促進して、同期の複雑さ(つまり、通信するメモリを共有するのではなく、通信によりデータを共有する)を促進しようとします。ところで、リファレンスGoの実装には、プロファイラーや競合検出器など、パフォーマンスと同時実行の問題に対処するためのツールが多数用意されています。
ページフォールトと「複数のスレッドの偽造」に関して、Goは複数のシステムスレッドでゴルーチンをスケジュールできることに注意してください。1つのスレッドが何らかの理由(ページフォールト、システムコールのブロック)でブロックされた場合、他のスレッドが他のゴルーチンをスケジュールおよび実行し続けることを妨げません。これで、ページフォールトがOSスレッドをブロックし、すべてのゴルーチンがこのスレッドでスケジュールされることになります。ただし、実際には、Goヒープメモリはスワップアウトされることは想定されていません。これはJavaでも同じです。ガベージコレクションされた言語は、とにかく仮想メモリをうまく収容しません。プログラムがページフォールトを適切な方法で処理する必要がある場合(おそらく、オフヒープメモリを管理する必要があるため)。その場合、
IMOでは、ゴルーチンはグリーンスレッドではありません。Go言語と現在の実装は、主にこれらの批判に対処しています。