Forum: JRuby newb question: ThreadSafe::Array

47afa33c7000daeac75e2edc3d67428b?d=identicon&s=25 Jon Beyer (jbeyer)
on 2013-11-13 01:30
(Received via mailing list)
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]
54147c1a1223b425d4f4f7947c9bba46?d=identicon&s=25 Ariel Valentin (Guest)
on 2013-11-13 04:04
(Received via mailing list)
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.
47afa33c7000daeac75e2edc3d67428b?d=identicon&s=25 Jon Beyer (jbeyer)
on 2013-11-13 04:42
(Received via mailing list)
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
666badca71c452ae51c999971419b506?d=identicon&s=25 Joe Kutner (Guest)
on 2013-11-13 05:00
(Received via mailing list)
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:
http://deployingjruby.blogspot.com/2013/07/why-jru...
This topic is locked and can not be replied to.