4

私の仮定:

  • MRI ruby​​ 1.8.X にはネイティブ スレッドはありませんが、グリーン スレッドがあります。

  • OS は、これらのグリーン スレッドを認識していません。

  • IO 負荷の高い操作を発行すると、適切な IO 割り込みが返されるまでプロセス全体が中断されます。

これらを使用して、次のことを行う単純な ruby​​ プログラムを作成しました。

  • "working!" を出力するスレッドを開始します。一秒ごと。

  • 「メイン」スレッドで大きな (1 GB) ファイルをコピーするための IO 要求を発行します。

グリーン スレッドは OS からは見えないため、プロセス全体が「ブロックされた」キューと「動作中」のキューに置かれると推測できます。緑のスレッドは実行されません。驚くべきことに、それは動作します:S

そこで何が起こっているか知っている人はいますか?ありがとう。

4

2 に答える 2

4

アトミックなカーネル ファイル コピー操作はありません。カーネルに出入りするのは、かなり短い読み取りと書き込みの多くです。

その結果、プロセスは常に制御を取り戻します。信号が配信されます。

グリーン スレッドは、Ruby レベルのスレッド ディスパッチャーを低レベルの I/O とシグナル受信にフックすることで機能します。これらのフックが定期的に制御をキャッチする限り、緑色のスレッドはより多くの並行スレッドとまったく同じように動作します。

Unix は元々、ユーザー プロセス環境用に、スレッドをまったく認識していませんが、美しく単純な抽象マシン モデルを持っていました。

年月が経つにつれて、一般的な並行性のサポートと、特にスレッドのサポートが、2 つの異なる方法で少しずつ追加されました。

  1. I/O がブロックするかどうかをチェックする、I/O がブロックする場合に失敗する (後で再試行する)、信号の遅い tty I/O を中断するが透過的にそれに戻るなど、多くの小さな工夫が追加されました。 API は、複数の形式で存在する各クラッジがマージされました。たくさんの選択肢。1.
  2. アドレス空間を共有する複数のカーネル可視プロセスの形式でのスレッドの直接サポートも追加されました。これらのスレッドは危険でテストできませんが、広くサポートされ、使用されています。ほとんどの場合、プログラムはクラッシュしません。時間が経つにつれて、ハードウェアがより多くの真の並行性をサポートするようになるため、潜在的なバグが明らかになります。Ruby がその悪夢を完全にサポートしていないことについて、私は少しも心配していません。

1. 標準の良いところは、非常に多くの標準があることです。

于 2013-01-31T23:26:56.820 に答える
3

MRI 1.9 が開始されると、2 つのネイティブ スレッドが生成されます。1 つのスレッドは VM 用で、もう 1 つはシグナルの処理に使用されます。Rubinis は、JVM と同様にこの戦略を使用します。パイプを使用して、他のプロセスからの情報を伝達できます。

FileUtilsモジュールに関しては、cdpwdmkdirrmlncpmvおよびメソッドはすべてchmod、サブモジュールの内部 API を使用して OS ネイティブ ユーティリティにある程度アウトソーシングされ、2 番目のスレッドは an からのシグナルを待つために残されます。外プロセス。これらのメソッドは完全にスレッドセーフであるため、インタープリターをロックする必要はなく、メソッドが互いにブロックすることはありません。chowntouchStreamUtils

編集:

MRI 1.8.7 は非常にスマートで、スレッドが何らかの外部イベント (ブラウザーが HTTP 要求を送信するなど) を待機している場合、スレッドをスリープ状態にして、データが検出されると起動できることを認識しています。- Evan Phoenix 氏、Engine Yard in Ruby、Concurrency、および You

FileUtils の実装の基本的な実装は、ソースを見ることから 1.8.7 の意味をあまり変更していません。1.8.7 はまた、スリーピー タイマー スレッドを使用して IO 応答を待ちます。1.9 での主な違いは、グリーン スレッドではなくネイティブ スレッドを使用することです。また、スレッドのソース コードはより洗練されています。

スレッドセーフとは、プロセス間で共有されるものがないため、グローバル インタープリターをロックする理由がないことを意味します。Ruby が特定のタスクを実行するときに「ブロック」するという誤解があります。スレッドがブロックする必要があるとき、つまり CPU を使用せずに待機する必要があるときはいつでも、Ruby は単純に別のスレッドをスケジュールします。ただし、CPU の 20% を使用して応答を待機しているラック サーバーなどの特定の状況では、インタープリターのロックを解除し、待機中に並行スレッドが他の要求を処理できるようにすることが適切な場合があります。これらのスレッドは、ある意味で並行して動作しています。GIL はrb_thread_blocking_regionAPI でロック解除されます。これは、このテーマに関する良い投稿です。

于 2013-01-31T22:43:24.090 に答える