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/.

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

···

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}

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

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

···

On Jun 18, 2008, at 6:11 PM, Rob Biedenharn wrote:

On Jun 18, 2008, at 5:23 PM, Bob Bobrov wrote:

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/\.