Problem of share variable in function using thread

N

Nita Neou

Hi All

I got a little problem when using thread function and variable, let's
say this code :

require 'rubygems'
require 'watir'
require 'thread'

def testfunc(id)
total = id + 5
puts "id #{id} is #{total}"
end

threads = []
numberlist = [1, 2, 3]
for id in numberlist
threads << Thread.new {testfunc(id)}
end

threads.each { |aThread| aThread.join }

my output is :
[sophoah@fedora ]$ ruby test.rb
id 3 is 8
id 3 is 8
id 3 is 8

The fact is that I would like this output :
id 1 is 6
id 2 is 7
id 3 is 8

I am suspecting that all variable id, and total are all share among
all the thread, is that right ? why ? I thought variable in a block
were not share among variable ? How can I fix this problem ?

Thanks a lot for your help on it,
Regards
Nita
 
R

Roger Pack

threads = []
numberlist = [1, 2, 3]
for id in numberlist
threads << Thread.new {testfunc(id)}
end
...

The fact is that I would like this output :
id 1 is 6
id 2 is 7
id 3 is 8

what's happening is that "id" is being changed as it iterates through
the numberlist.
So when each thread starts and finally gets around to running
"testfunc(id)" they all call it with the end value.

The fix is that you can pass a value "through" to the new threads, thus:

Thread.new(id) {|id| testfunc(id) }

Then it will preserve the original value.
-r
 
J

Jesús Gabriel y Galán

Hi All

I got a little problem when using thread function and variable, let's
say this code :

require 'rubygems'
require 'watir'
require 'thread'

def testfunc(id)
=A0 =A0 =A0 =A0total =3D id + 5
=A0 =A0 =A0 =A0puts "id #{id} is #{total}"
end

threads =3D []
numberlist =3D [1, 2, 3]
for id in numberlist
=A0 =A0 =A0 =A0threads << Thread.new {testfunc(id)}
end

threads.each { |aThread| =A0aThread.join }

my output is :
[sophoah@fedora ]$ ruby test.rb
id 3 is 8
id 3 is 8
id 3 is 8

The fact is that I would like this output :
id 1 is 6
id 2 is 7
id 3 is 8

I am suspecting that all variable id, and total are all share among
all the thread, is that right ? why ? I thought variable in a block
were not share among variable ? How can I fix this problem ?

Blocks in Ruby are closures, this means that inside the block you pass
to Thread.new, the variable id is the same.
The Thread class has a way to avoid this, take a look at the constructor:

http://ruby-doc.org/core/classes/Thread.html#M000437

You can pass parameters to #new and it will pass them to the block.
You can use this technique to use a variable in the block that is
different for each thread, like this:

def testfunc(id)
total =3D id + 5
puts "id #{id} is #{total}"
end

threads =3D []
numberlist =3D [1, 2, 3]
for id in numberlist
threads << Thread.new(id) {|my_id| testfunc(my_id)}
end

threads.each { |aThread| aThread.join }


$ ruby threads.rb
id 1 is 6
id 2 is 7
id 3 is 8


Jesus.
 
N

Nita Neou

I got a little problem when using thread function and variable, let's
say this code :
require 'rubygems'
require 'watir'
require 'thread'
def testfunc(id)
       total = id + 5
       puts "id #{id} is #{total}"
end
threads = []
numberlist = [1, 2, 3]
for id in numberlist
       threads << Thread.new {testfunc(id)}
end
threads.each { |aThread|  aThread.join }
my output is :
[sophoah@fedora ]$ ruby test.rb
id 3 is 8
id 3 is 8
id 3 is 8
The fact is that I would like this output :
id 1 is 6
id 2 is 7
id 3 is 8
I am suspecting that all variable id, and total are all share among
all the thread, is that right ? why ? I thought variable in a block
were not share among variable ? How can I fix this problem ?

Blocks in Ruby are closures, this means that inside the block you pass
to Thread.new, the variable id is the same.
The Thread class has a way to avoid this, take a look at the constructor:

http://ruby-doc.org/core/classes/Thread.html#M000437

You can pass parameters to #new and it will pass them to the block.
You can use this technique to use a variable in the block that is
different for each thread, like this:

def testfunc(id)
  total = id + 5
  puts "id #{id} is #{total}"
end

threads = []
numberlist = [1, 2, 3]
for id in numberlist
 threads << Thread.new(id) {|my_id| testfunc(my_id)}
end

threads.each { |aThread|  aThread.join }

$ ruby threads.rb
id 1 is 6
id 2 is 7
id 3 is 8

Jesus.

Thanks both of you for your answer.

Regards
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,954
Messages
2,570,116
Members
46,704
Latest member
BernadineF

Latest Threads

Top