![]() |
Threads and synchronized access to an array
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} -- Posted via http://www.ruby-forum.com/. |
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 |
Re: Threads and synchronized access to an array
On Jun 18, 2008, at 6:11 PM, Rob Biedenharn wrote:
> On Jun 18, 2008, at 5:23 PM, Bob Bobrov wrote: >> Hi everyone! >> A n00b question - I have a following ruby code: >> =============================================== >> snip >> 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: >> snip > 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 If you remove the sleep and initialize with @arr=(1..10000).to_a you see the kind of result you probably want where the @mutex.synchronize block is really controlling the access. -Rob Rob Biedenharn http://agileconsultingllc.com Rob@AgileConsultingLLC.com |
Re: Threads and synchronized access to an array
Rob Biedenharn wrote:
> 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 Thank you, exactly what I need! -- Posted via http://www.ruby-forum.com/. |
| All times are GMT. The time now is 08:18 PM. |
Powered by vBulletin®. Copyright ©2000 - 2013, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.