From: Rob Biedenharn Date: 2008-06-19T07:11:02+09:00 Subject: Re: Threads and synchronized access to an array On Jun 18, 2008, at 5:23 PM, Bob Bobrov wrote: > Hi everyone! > A n00b question - I have a following ruby code: > =============================================== > @arr = [ 1, 2, 3, 4, 5, 6, 7, 8 ] > > def iterate(thread_number) > @arr.each do |line| > puts "#{line} - I am thread number #{thread_number}" > end > end > > number_of_threads = 4 > > threads = [] > number_of_threads.times do |t| > threads[t] = Thread.new do > iterate(t) > end > end > > threads.each {|t| t.join} > ================================================ > > > > The output for this code is: > ================================================ > 1 - I am thread number 0 > 2 - I am thread number 0 > 3 - I am thread number 0 > 4 - I am thread number 0 > 5 - I am thread number 0 > 6 - I am thread number 0 > 7 - I am thread number 0 > 8 - I am thread number 0 > 1 - I am thread number 1 > 2 - I am thread number 1 > 3 - I am thread number 1 > 4 - I am thread number 1 > 5 - I am thread number 1 > 6 - I am thread number 1 > 7 - I am thread number 1 > 8 - I am thread number 1 > 1 - I am thread number 2 > 2 - I am thread number 2 > 3 - I am thread number 2 > 4 - I am thread number 2 > 5 - I am thread number 2 > 6 - I am thread number 2 > 7 - I am thread number 2 > 8 - I am thread number 2 > 1 - I am thread number 3 > 2 - I am thread number 3 > 3 - I am thread number 3 > 4 - I am thread number 3 > 5 - I am thread number 3 > 6 - I am thread number 3 > 7 - I am thread number 3 > 8 - I am thread number 3 > ================================================ > > > What should be changed in this code to make the output looks like > this? > ================================================ > 1 - I am thread number #{thread_number} > 2 - I am thread number #{thread_number} > 3 - I am thread number #{thread_number} > 4 - I am thread number #{thread_number} > 5 - I am thread number #{thread_number} > 6 - I am thread number #{thread_number} > 7 - I am thread number #{thread_number} > 8 - I am thread number #{thread_number} > ================================================ > > I want to iterate the array values only one time by some number of > threads, how should I control the access to array values? Each thread > must be prohobited from using the array values, which have been > already > used by other threads. > > I was trying to change the code like this: > @mutex = Mutex.new > @arr = [ 1, 2, 3, 4, 5, 6, 7, 8 ] > > @mutex.synchronize { > def iterate(thread_number) > @arr.each do |line| > puts "#{line} - I am thread number #{thread_number}" > end > end > } > > number_of_threads = 4 > > threads = [] > number_of_threads.times do |t| > threads[t] = Thread.new do > iterate(t) > end > end > > threads.each {|t| t.join} > > and this: > @mutex = Mutex.new > @arr = [ 1, 2, 3, 4, 5, 6, 7, 8 ] > > > def iterate(thread_number) > @arr.each do |line| > puts "#{line} - I am thread number #{thread_number}" > end > end > > > number_of_threads = 4 > > threads = [] > number_of_threads.times do |t| > threads[t] = Thread.new do > @mutex.synchronize { > iterate(t) > } > end > end > > threads.each {|t| t.join} Perhaps: require 'thread' @mutex = Mutex.new @arr = [ 1, 2, 3, 4, 5, 6, 7, 8 ] def iterate(thread_number) while @arr.length > 0 do sleep 0.01 @mutex.synchronize { if line = @arr.shift puts "#{line} - I am thread number #{thread_number}" end } end end number_of_threads = 4 threads = [] number_of_threads.times do |t| threads[t] = Thread.new do iterate(t) end end threads.each {|t| t.join} __END__ without the sleep, the first thread started grabs them all before the next one gets a chance. You never did anything to alter the @arr that all threads saw. I haven't played with threads for a long time, but unless you change something about @arr, every iterate() will operate once for each element. You run into trouble with the Array#each if you modify the contents of the array inside the block. -Rob Rob Biedenharn http://agileconsultingllc.com Rob@AgileConsultingLLC.com