2016-07-11 4 views
0
で起こっていない

プログラム:相互排他は、Ruby

def inc(n) 
    n + 1 
end 

sum = 0 
threads = (1..10).map do 
    Thread.new do 
     10_000.times do 
      sum = inc(sum) 
     end 
    end 
end 
threads.each(&:join) 
p sum 

出力:

$ ruby MutualExclusion.rb 
100000 
$ 

上記のプログラムの私の予想出力が10万未満です。上記のプログラムは10個のスレッドを作成し、スレッド は共有変数 'sum'を10,000回更新します。しかし、プログラムの実行中、相互排除は間違いなく起こります。こちらでは、 の相互排除は扱わないためです。だから私は100,000以下の出力を期待しています。しかしそれは出力として正確に100,000を与える。どのように が起こったのですか?ここで相互排除を扱うのは誰ですか?そして私はどのようにこの問題を実験しますか(ME)。

+0

あなたはMRIやJRubyの中で、あなたのコードをテストしましたか? – spickermann

+0

@spickermannいいえ、私は初心者です。私はそれを知らなかった。 – mrg

+0

@spickermannは言った、MRI :) – mudasobwa

答えて

0

Ruby(MRI)のデフォルトインタープリタは、スレッドを並行して実行しません。競合状態が予期せぬ予期しない動作を引き起こさないようにするメカニズムは、Global Interpreter Lock(GIL)です。

あなたはここで、非常に類似したデモンストレーションを含め、これについての詳細を学ぶことができます。http://www.jstorimer.com/blogs/workingwithcode/8085491-nobody-understands-the-gil

+0

ちょうど私は気持ち悪いです。それが正しいと思いますか?相互排除を適切に処理するのではなく、「一度に1つのスレッドしかRubyコードを実行できない」というようにプロパティを完全に設定しても問題ありません。このため、スレッドの並列実行が回避されます。これはスレッドの主な使用を破壊します。あなたはこのことについてどう思いますか。それは賛否両論ですか? – mrg

+0

@mrg必ずしもそうではありません。それはあなたが何をしているかによって異なります。特にWebサービスを構築する場合は、IO(たとえばAPIリクエスト)を多くすることになります。スレッドスケジューラはIOがバックグラウンドで実行している間に一時停止し、その間に他の要求を処理することができます。しかし、CPUバインドのタスクでは、別のインタプリタが推奨されています(rbx/rubiniusはかなり良いです)。 – coreyward

+0

MRIはウェブサービスには適していますが、rbxはCPUバウンドタスクに適していますか? – mrg

関連する問題