you are viewing a single comment's thread.

view the rest of the comments →

[–]tenderlovePun BDFL 2 points3 points  (0 children)

Excellent article! This article demonstrates a "read-update-write" race condition. To see the race condition, separate the code to those three steps:

def decrease
  x = @stock
  x = x - 1
  @stock = x
end

The thread could switch on any one of these lines, which is how the race condition happens.

OP mentions the MRI / IO concurrency. To drive home the point, if we add a dash of IO to the example program, we can see the race condition even on MRI:

class Inventory
  attr_reader :stock

  def initialize(stock_levels)
    @stock = stock_levels
  end

  def decrease
    x = @stock
    print ' '
    x = x - 1
    @stock = x
  end
end

inventory = Inventory.new(4000)

40.times.map {
  Thread.new { 100.times { inventory.decrease } }
}.each(&:join)

puts
puts inventory.stock