15

Ruby では、このコードがarray多くのスレッドによって変更された場合、スレッドセーフではありません。

array = []
array << :foo # many threads can run this code

<<操作がスレッドセーフでないのはなぜですか?

4

5 に答える 5

10

実際に MRI (Matz の Ruby 実装) を使用すると、GIL (Global Interpreter Lock) によって純粋な C 関数がアトミックになります。

Array#<<は MRI で純粋な C コードとして実装されるため、この操作はアトミックになります。ただし、これは MRI にのみ適用されることに注意してください。JRuby ではそうではありません。

何が起こっているのかを完全に理解するには、次の 2 つの記事を読むことをお勧めします。

誰も GIL を理解してい
ない 誰も GIL を理解していない - パート 2

于 2013-07-20T23:10:57.463 に答える
9

arrayのような操作を適用するときのプログラム変数です<<。それは次の 3 つのステップで行われます。

  • 変数は最初に CPU レジスタにコピーされます。
  • CPU は計算を実行します。
  • CPU は結果を変数メモリに書き戻します。

したがって、この高レベルの単一操作は 3 つのステップで実行されます。これらのステップの間に、スレッドコンテキストの切り替えにより、他のスレッドが変数の同じ (古い) 値を読み取る可能性があります。そのため、アトミック操作ではありません。

于 2013-07-20T18:10:16.420 に答える
1

Ruby は非常に高水準の言語であるため、OS レベルで本当にアトミックなものはありません。非常に単純なアセンブリ操作のみが OS レベル (OS 依存) でアトミックであり、Ruby のすべての操作は、単純なものであっても、1 + 1メソッド ルックアップ、ガベージ コレクション、オブジェクトの初期化、スコープ計算など、実行される数百または数千のアセンブリ命令に対応します。

操作をアトミックにする必要がある場合は、ミューテックスを使用します。

于 2013-07-20T19:01:29.510 に答える
0

@Linuxios と @TheTinMan からの引用: 高水準言語 (HLL) 操作は一般にアトミックではありません。原子性は、(一般的に) シングルスレッド プログラムでは問題になりません。マルチスレッド プログラムでは、ユーザー (プログラマー) は単一の HLL 操作よりもはるかに高い粒度で推論する必要があるため、アトミックな個々の HLL 操作を使用しても、実際にはそれほど役に立ちません。反対に、HLL 操作をアトミックにするには、少なくとも最新のハードウェアでは前後に数個のマシン命令しか必要ありませんが、静的 (バイナリ サイズ) と動的 (実行時間) のオーバーヘッドが加算されます。さらに悪いことに、コンパイラはアトミック操作間で命令を移動できないため、明示的な原子性はすべての最適化をほとんど無効にします。実質的なメリットなし + 多額のコスト = 非スターター。

于 2013-07-22T21:14:54.650 に答える