19

重複の可能性:
ruby​​ には Java に相当する synchronize キーワードがありますか?

Java では、関数定義で 'synchronized' キーワードを使用するだけで、メソッドを 'synchronized' にすることができます。

Ruby でそれを行うにはどうすればよいでしょうか。

4

1 に答える 1

22

Synchronize キーワードは Ruby にはありません。あるいは、単にメソッド呼び出しをラップすることもできますMutex(つまり、Lock の派手な言葉)。

そのクラスの新しい共有 Mutex を作成します (全員が同じ変数にアクセスするには、同じ Mutex (ロック) を使用する必要があります)。

NUM_THREADS = 4

class Foo
  def initialize
    @my_mutex = Mutex.new
    @my_val = 0 # should be private
  end

  def synchronize(&block)
    # to see what it does without the mutex in this example:
    # 1) comment this line
    @my_mutex.synchronize(&block)
    # 2) uncomment this line
    # yield
  end

  def current_value
    synchronize do
      @my_val
    end
  end

  def modify
    # the value should be 0 before and 0 after, if the Mutex is used correctly
    synchronize do
      @my_val += 1
      sleep 0.25
      @my_val -= 1
      sleep 0.25
    end
  end
end

foo = Foo.new

threads = []

# spawn N threads, all trying to change the value
threads += (1..NUM_THREADS).map { |i|
  Thread.new {
    puts "thread [##{i}]: modifying"
    foo.modify
  }
}

# spawn checking thread
threads << Thread.new {
  # print the value twice as fast as the other threads are changing it, so we are more likely to stumble upon wrong state
  (NUM_THREADS * 2).times {
    puts "thread [check]: checking..."
    raise if foo.current_value != 0 # locking failed, crash
    sleep 0.25
  }
}

threads.map { |t| t.join } # wait for all threads

puts "even though it took a while longer, it didn't crash, everyone is happy, managers didn't fire me... it worked!"

http://apidock.com/ruby/Mutexを参照

これらすべてのロックにより、プログラムの実行時間が長くなります。速度は、Ruby の実装 (グリーン スレッド、ネイティブ スレッドなど) とコア数によって異なります。上記の例でミューテックスを無効にすると、スレッドのチェックで保護が発生するため、プログラムはすぐにクラッシュします。チェックスレッドもミューテックスを使用する必要があることに注意してください。そうしないと、他のスレッドによる変更の途中で値を読み取ることができるためです。つまり、全員が同じミューテックスを使用してその変数にアクセスする必要があります。

synchronizedキーワードの不足を回避するためにsynchronize、クラス defined を使用するメソッドを定義しMutexました。

于 2012-12-30T12:40:42.827 に答える