为什么在Ruby中没有比赛条件 [英] Why no race condition in Ruby

查看:73
本文介绍了为什么在Ruby中没有比赛条件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用多线程示例.我正在尝试使用以下代码来产生竞争条件.但是我总是得到相同(正确)的输出.

I was experimenting with multithreading examples. I am trying to produce a race condition using the following code. But I am always getting the same (correct) output.

class Counter
  attr_reader :count
  def initialize
    @count = 0
  end
  def increment
    @count += 1
  end
  def decrement
    @count -= 1
  end
end
c = Counter.new
t1 = Thread.start { 100_0000.times { c.increment } }
t2 = Thread.start { 100_0000.times { c.increment } }
t1.join
t2.join
p c.count #200_0000

我能够使用每个线程中更少的迭代次数来观察Java中的竞争状况.是我运行的次数不足以产生竞争条件,还是+/-在Ruby中是线程安全的?我正在使用ruby 2.0.0p247

I am able to observe the race condition in Java using much less number of iterations in each thread. Is it that I am not running it enough number of times to produce a race condition, or +/- are Thread safe in Ruby? I am using ruby 2.0.0p247

推荐答案

这是因为MRI Ruby线程由于GIL并非真正并行(请参阅

This is because MRI Ruby threads are not really parallel due to GIL (see here), at CPU level they are executed one at a time.

一个线程中的每个命令一次执行一次,因此每个线程中的@count总是正确更新.

Each command in a thread is executed one at a time hence @count in each thread is always updated correctly.

种族条件可以通过添加另一个变量来模拟,例如:

Race condition can be simulated by adding another variable like:

class Counter
    attr_accessor :count, :tmp

    def initialize
        @count = 0
        @tmp = 0
    end

    def increment
        @count += 1
    end


end

c = Counter.new

t1 = Thread.start { 1000000.times { c.increment; c.tmp += 1 if c.count.even?; } }
t2 = Thread.start { 1000000.times { c.increment; c.tmp += 1 if c.count.even?; } }

t1.join
t2.join

p c.count #200_0000
p c.tmp # not 100_000, different every time

给出了一个很好的竞争条件示例此处,出于完整性考虑,复制在下方

A nice example of race condition is given here, copied below for completeness

class Sheep
  def initialize
    @shorn = false
  end

  def shorn?
    @shorn
  end

  def shear!
    puts "shearing..."
    @shorn = true
  end
end


sheep = Sheep.new

5.times.map do
  Thread.new do
    unless sheep.shorn?
      sheep.shear!
    end
  end
end.each(&:join)

这是我在MRI 2.0上多次运行后看到的结果.

Here's the result I see from running this on MRI 2.0 several times.

$ ruby​​ check_then_set.rb =>剪切...

$ ruby check_then_set.rb => shearing...

$ ruby​​ check_then_set.rb =>剪切...剪切...

$ ruby check_then_set.rb => shearing... shearing...

$ ruby​​ check_then_set.rb =>剪切... 剪切...

$ ruby check_then_set.rb => shearing... shearing...

有时候同一只羊被砍两次!

Sometimes the same sheep is being shorn twice!

这篇关于为什么在Ruby中没有比赛条件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆