Examples 2 and 3 are exactly the same. Modules and classes are also objects, and defining a singleton method on a object actually defines it on its singleton class.
With that said, and since you have already established instance variable access is thread safe, examples 2 and 3 are thread safe. Example 1 should also be thread safe, but it is inferior to the other two because it requires manual variable synchronization.
However, if you need to take advantage of the fact that class variables are shared within the inheritance tree, you may have to use the first approach.
The inherent thread safety of the Ruby language depends on the implementation.
MRI, before 1.9, implemented threads at the VM level. This means that even though Ruby is capable of scheduling code execution, nothing is really running in parallel within a single Ruby process. Ruby 1.9 uses native threads synchronized with a global interpreter lock. Only the context which holds the lock may execute code.
n, x = 10, 0
n.times do
Thread.new do
n.times do
x += 1
end
end
end
sleep 1
puts x
# 100
The value of x
is always consistent on MRI. On JRuby, however, the picture changes. Multiple executions of the same algorithm yielded the values 76
, 87
, 98
, 88
, 94
. The result could be anything because JRuby uses Java threads, which are real threads and execute in parallel.
Just like in the Java language, manual synchronization is required in order to safely use threads in JRuby. The following code always results in consistent values for x
:
require 'thread'
n, x, mutex = 10, 0, Mutex.new
n.times do
Thread.new do
n.times do
mutex.synchronize do
x += 1
end
end
end
end
sleep 1
puts x
# 100
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…