问题 Ruby中并发的同步方法[重复]


可能重复:
ruby是否具有Java等效的synchronize关键字? 

在Java中,我们可以通过在函数定义中使用'synchronized'关键字来使方法“同步”。

我们如何在Ruby中做到这一点?


9992
2017-12-30 12:32


起源

抱歉,我的问题与上述评论中的链接类似。请随时关闭这个 - Imran Omar Bukhsh
我不会投票结束。答案在这个问题上更好。 - Ismael Abreu


答案:


Ruby中不存在Synchronize关键字。或者只是将方法调用包装起来 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 它使用定义的类 Mutex


14
2017-12-30 12:40



那这个呢 stackoverflow.com/questions/3208462/...? - Imran Omar Bukhsh
第一个代码示例很好,但是 Mutex.new.synchronize 没用因为您没有保留对新创建的互斥锁的引用,所以没有其他线程可以尝试锁定它,因此它永远不会从关键区域(这是互斥锁的整点)中排除任何线程。 - Alex D
我不确定这是否属实,但@AlexD所说的完全有道理! - Ismael Abreu
@AlexD我偶然发现了这个答案并更新了它以反映你的评论,因为你是对的。 - Dalibor Filus
现在看起来好多了! - Alex D