Newb question: ThreadSafe::Array

I downloaded and was experimenting with the ThreadSafe::Array class, but
am
confused as to how the class is safer than the conventional array class.

In the following code sample, the result is never 0, as one might (or
might
not) expect it to be. What am I misunderstanding about the functioning
of
this class? Could someone illustrate a simple example where ThreadSafe
functions, but a conventional array would fail?

Thanks in advance,
Jon

require ‘thread_safe’

N = ARGV[0].to_i
array = ThreadSafe::Array.new
array[0] = 0
threads = []

( 1…N ).each do |i|
threads << Thread.new {
array[0] += 1
array[0] -= 1
}
end

threads.each { |thread| thread.join }

puts array[0]

I may be wrong about this but the “+=” line should not be an atomic
operation. Multiple threads may read the value in sequence and then
mutate the values in sequence. What I think you may be looking for is an
atomic increment function.

Thanks,
Ariel

Sent from my mobile device. Please excuse any errors.

This should do it:

data = [] # or ThreadSafe::Array.new
threads = []
16.times do |m|
threads << Thread.new do
16.times do |n|
data << m * n
end
end
end

threads.map(&:join)
puts “size => #{data.size}”

I wrote a blog a while back describing why:

Ariel, that thought occurred to me, and I think you must be right. What
I’m still a bit confused by is that I haven’t been able to create a code
sample where the standard Array fails, but ThreadSafe::Array performs as
the user intended in multi-threaded code. My previous example failed
for
both Array and ThreadSafe::Array. The example below works for both,
although one might think it would fail with Array.
Can anyone out there demonstrate an example where Array fails and
ThreadSafe::Array behaves as the user intended?

Cheers,
Jon

N = ARGV[0].to_i
array = []
threads = []

( 1…N ).each do |i|
threads << Thread.new {
array << 1
}
end

threads.each { |thread| thread.join }

puts array.length