1

簡単な Google 検索を行ったところ、Ruby のアトミック性について書かれているほとんどすべてが、操作を Mutex でラップすることを提案しています。ただし、シグナルが同期されたコードを中断する可能性があるため、このアプローチはアトミック性の通常の定義を満たさないのではないかと思います。例 ( Ruby Best Practicesから引用):

lock = Mutex.new

# XXX this is an example of what NOT to do inside a signal handler:
trap(:USR1) do
  lock.synchronize do
    # if a second SIGUSR1 arrives here, this block of code
    # will fire again.   Attempting Mutex#synchronize twice
    # the same thread leads to a deadlock error
  end
end

高水準言語では原子性がそれほど重要ではないことは理解していますが、研究のために、GIL ( MRI 2.0.0 など) を使用した実装と、JRuby 1.7.4 や Rubinius を使用しない実装 について、この問題に関する標準的な回答を得たいと思います。 1.2.4

4

1 に答える 1

1

このトピックに関する知識は非常に限られています。しかし、私はできる限り最善を尽くして答えようとします。

Jesse Storimer が並行性について書いた非常に優れた記事があります。これについては、3 部すべてを読むことを強くお勧めします。

http://www.jstorimer.com/blogs/workingwithcode/8100871-nobody-understands-the-gil-part-2-implementation

パート 2 の結論は、ネイティブ C メソッドの実装がアトミックであることを GIL が保証したということです。

あなたが挙げた例は、実際には原子性よりも再入の問題です。それが同じものなのか、それともどれほど密接に関連しているのかはわかりません。

記事の説明のように、ruby はコールバックが同期であるイベント駆動型プログラミングとは異なります。つまり、シグナル USR1 を 2 回送信すると、最初のハンドラーが終了した後に 2 番目のハンドラーが実行されます。したがって、mutex を 2 回ロックすることはありません。

しかし、Ruby のシグナル処理は非同期です。つまり、シグナルを 2 回送信した場合です。2 番目のハンドラーは最初のハンドラーを中断します。最初のハンドラーはすでにロックを取得しているため、同じロックを取得しようとする 2 番目のハンドラーは例外をスローします。そして、この問題は Ruby 固有の問題ではないと私は信じています。

この問題を解決する方法の 1 つは、シグナル処理を行うためのキューを作成することです。これに対する別の解決策は、「セルフパイプ」トリックと呼ばれる方法を使用することです。どちらも方法。この記事でも素晴らしい Jesse Storimer によって説明されています。

http://rubysource.com/the-self-pipe-trick-explained/

したがって、MRI 2.0.0 にはまだ GIL があると思います。そのため、Ruby はネイティブ C メソッドがアトミックであることのみを保証します。

JRuby は JVM でサポートされているため、すべてのスレッドとロック メカニズムは JVM の上に実装されていると思います。

Rubinius 1.2 にもまだ GIL があるので、MRI と同じになると思います。しかし、Rubinius 2.x では GIL が削除されています。私は Rubinius の経験があまりないので、完全にはわかりません。

また、ルビーでマルチスレッドアプリケーションを使用している場合は、質問に答えてください。Mutex クラスは、ブロックが一度に 1 つのスレッドによってのみ実行されるように保護する必要があります。

于 2013-08-07T21:33:28.133 に答える