Mutex を使用した Ruby スレッドの同時実行の問題

概要

require 'thread'

mutex = Mutex.new


shared_resource = 0

  for i in 0..10000
    Thread.new do
      mutex.synchronize { shared_resource += 1 }
    end
    Thread.new do
      mutex.synchronize { shared_resource -= 1 }
    end
  end

puts shared_resource

このRubyプログラムを実行してmutex.synchronizeをテストし、実行するたびに0を取得しようとしていますが、このプログラムを実行するたびにランダムな値が得られます。 0 を取得するためにこれを解決するのに助けが必要です。また、Ruby で Mutex とロックを使用する方法を理解するのに役立ちます。

解決策

synchronize はブロックの実行中にミューテックスをロックするため、問題はミューテックスではありません。あなたの問題は、putsshared_resource に到達したときにスレッドの実行が完了していないことです。

これを解決するには、たとえば Thread#join を呼び出して、すべてのスレッドが完了していることを確認する必要があります。

require 'thread'

mutex = Mutex.new

shared_resource = 0
threads = []

400.times do |i|
  threads << Thread.new do
    mutex.synchronize {shared_resource += 1}
  end
  threads << Thread.new do
    mutex.synchronize {shared_resource -= 1}
  end
end

puts shared_resource
#=> some number

# see how many threads are still running 
puts threads.map(&:status)

threads.map(&:join)

puts shared_resource
#=> 0