Threads and synchronized access to an array

Discussion in 'Ruby' started by Bob Bobrov, Jun 18, 2008.

  1. Bob Bobrov

    Bob Bobrov Guest

    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/.
     
    Bob Bobrov, Jun 18, 2008
    #1
    1. Advertising

  2. 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 Biedenharn, Jun 18, 2008
    #2
    1. Advertising

  3. 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 Biedenharn, Jun 18, 2008
    #3
  4. Bob Bobrov

    Bob Bobrov Guest

    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/.
     
    Bob Bobrov, Jun 19, 2008
    #4
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Jerry
    Replies:
    4
    Views:
    131,854
    tonni
    Aug 11, 2010
  2. Pep
    Replies:
    6
    Views:
    29,285
  3. dmcreyno
    Replies:
    9
    Views:
    9,570
    Mark Space
    Jun 27, 2006
  4. ankur
    Replies:
    4
    Views:
    1,447
    Eric Sosman
    Nov 28, 2008
  5. Luca D.
    Replies:
    5
    Views:
    537
    Mark Rafn
    Apr 30, 2009
Loading...

Share This Page