Ruby 类变量和初始化时间

Ruby 类变量和初始化时间,ruby,thread-safety,jruby,Ruby,Thread Safety,Jruby,如果我像这样创建一个类变量: class Song @@plays = 0 class << self def plays=( plays ) @@plays += plays end def plays @@plays end end end 是否可以让两个线程同时初始化@播放到0?类变量是在执行的哪个阶段创建的?@@plays=0是在Ruby计算类定义时设置的。这应该只发生一次,并且在启动线程之前 另

如果我像这样创建一个类变量:

class Song
  @@plays = 0

  class << self

    def plays=( plays )
      @@plays += plays
    end

    def plays
      @@plays
    end

  end

end

是否可以让两个线程同时初始化@播放到0?类变量是在执行的哪个阶段创建的?

@@plays=0
是在Ruby计算类定义时设置的。这应该只发生一次,并且在启动线程之前

另一方面,赋值方法
plays=
可以同时执行。因此,您应该将其包装在通话中,例如:

require 'thread'
require 'song'   # <- @@plays is set to 0 here

Song.plays #=> 0

semaphore = Mutex.new

t1 = Thread.new { semaphore.synchronize { Song.plays = 1 } }
t2 = Thread.new { semaphore.synchronize { Song.plays = 5 } }
t3 = Thread.new { semaphore.synchronize { Song.plays = 3 } }

[t1, t2, t3].each(&:join)
Song.plays #=> 9

你的代码对我不起作用。没有
Song#plays=
,而是将此方法创建为
Song
的singleton类上的类方法。我补充说,已修复。习惯性新增。不,仍然不起作用
Song.singleton_class.plays=
可以工作,但这可能不是您想要的。我修复了它,但它没有按预期工作。您现在既有一个实例方法,也有一个类方法,即
Song.singleton_class.plays=
Song.singleton_class#plays=
。后者相当于
Song.plays=
,但它不调用您的方法。提示:删除
类我是否应该在类变量中创建互斥,以确保它不是由2个线程同时创建的?同一个问题的措辞不同,您如何使Song类线程安全?@KieranAndrews是的,创建互斥锁就像
@@plays
,即在启动线程之前。我怀疑这能否回答问题。它无论如何都不能确保两个线程以
开头。@@plays==0
。它可以通过传递给
线程的可选参数进行设置。new
,但是仍然没有达到他想要达到的目的。@DavidUnric是的,几个线程可以从
(仍然)设置为
0
开始。但是一次只能有一个线程增加类变量。
require 'thread'
require 'song'   # <- @@plays is set to 0 here

Song.plays #=> 0

semaphore = Mutex.new

t1 = Thread.new { semaphore.synchronize { Song.plays = 1 } }
t2 = Thread.new { semaphore.synchronize { Song.plays = 5 } }
t3 = Thread.new { semaphore.synchronize { Song.plays = 3 } }

[t1, t2, t3].each(&:join)
Song.plays #=> 9
class Song
  @@plays = 0
  @@semaphore = Mutex.new

  def self.plays=(plays)
    @@semaphore.synchronize { @@plays += plays }
  end

  # ...
end