Ruby 中并发的同步方法 [英] Synchronized Method for concurrency in Ruby

查看:42
本文介绍了Ruby 中并发的同步方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

在 Java 中,我们可以通过在函数定义中使用同步"关键字来使方法同步".

In Java we can make a method 'synchronized' by just using the 'synchronized' keyword in the function definition.

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

How do we do it in Ruby?

推荐答案

Synchronize 关键字在 Ruby 中不存在.或者,只需将方法调用包装到 Mutex(即 Lock 的花哨词).

Synchronize keyword is not present in Ruby. Alternatively just can just wrap the method call to Mutex (i.e. fancy word for Lock).

为该类创建新的共享互斥锁(每个人都必须使用相同的互斥锁(锁)才能访问相同的变量):

Create new shared Mutex for that class (everyone must use the same Mutex (lock) to access the same variables):

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​​ 实现(例如绿色线程、本机线程......)和内核数量.如果在上面的示例中禁用互斥锁,则程序会立即崩溃,因为检查线程中的 raise Guard.请注意,检查线程也必须使用互斥锁,否则它仍然能够读取其他线程正在更改的值.IE.每个人都必须使用相同的互斥锁来访问该变量.

The program runs longer, because of all those locking. Speed depends on your ruby implementation (e.g. green threads, native threads..) and number of cores. If you disable mutex in this example above, the program crashes right away, because of the raise guard in checking thread. Note that the checking thread must use the mutex too, because otherwise it would still be able to read the value in the middle of change by other threads. I.e. everyone must use the same mutex to access that variable.

为了弥补 synchronized 关键字的缺失,我定义了方法 synchronize 使用定义的类 Mutex.

To make around the lack of synchronized keyword, I defined method synchronize which uses the class defined Mutex.

这篇关于Ruby 中并发的同步方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆