If I create a class variable like so:
class Song
@@plays = 0
class << self
def plays=( plays )
@@plays += plays
end
def plays
@@plays
end
end
end
An I have multiple threads accessing this class method and setting it in jruby:
t1 = Thread.new {st1 = Song.plays = 1}
t2 = Thread.new {st2 = Song.plays = 5}
t3 = Thread.new {st3 = Song.plays = 3}
Is it possible to have 2 threads initialise @@plays to 0 at the same time? At what stage in execution are class variables created?
@@plays = 0
is set when Ruby evaluates your class definition. This should only happen once and before starting your threads.
The assignment method plays=
on the other hand can be executed concurrently. You should therefore wrap it in a synchronize
call, e.g.:
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
Another option is to make Song#plays=
thread-safe by moving the mutex into the Song
class:
class Song
@@plays = 0
@@semaphore = Mutex.new
def self.plays=(plays)
@@semaphore.synchronize { @@plays += plays }
end
# ...
end