运维开发网

为什么Ruby中没有竞争条件

运维开发网 https://www.qedev.com 2020-07-23 16:15 出处:网络 作者:运维开发网整理
我正在尝试多线程示例.我正在尝试使用以下代码生成竞争条件.但我总是得到相同(正确)的输出. class Counter attr_reader :count def initialize @count = 0 end def increment @count += 1 end def decrement @count -= 1 end end c
我正在尝试多线程示例.我正在尝试使用以下代码生成竞争条件.但我总是得到相同(正确)的输出.

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

这是因为MRI Ruby线程由于GIL而不是真正的并行(见 here),在CPU级别它们一次执行一个.

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

可以通过添加另一个变量来模拟竞争条件:

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

一个很好的竞争条件的例子给出了here,下面复制完整性

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)

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

$ruby check_then_set.rb => shearing…

$ruby check_then_set.rb => shearing… shearing…

$ruby check_then_set.rb => shearing…

shearing…

Sometimes the same sheep is being shorn twice!

扫码领视频副本.gif

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号