Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Ruby > help on threads synchronization

Reply
Thread Tools

help on threads synchronization

 
 
Zd Yu
Guest
Posts: n/a
 
      05-13-2011
How to make two threads do something in turn, i.e., A => B => A => B
....?

I know the code below is not correct, but I do not know how to make it
correct. Could anybody help?

=======================================
mutex=Mutex.new

t=Thread.new {
while true
Thread.stop
puts "B move..."
Thread.main.wakeup
end
}

while true
puts "A move..."
t.wakeup
Thread.stop
end

--
Posted via http://www.ruby-forum.com/.

 
Reply With Quote
 
 
 
 
Robert Klemme
Guest
Posts: n/a
 
      05-13-2011
On Fri, May 13, 2011 at 9:33 AM, Zd Yu <(E-Mail Removed)> wrote:
> How to make two threads do something in turn, i.e., A =3D> B =3D> A =3D> =

B
> ....?
>
> I know the code below is not correct, but I do not know how to make it
> correct. Could anybody help?
>
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3 D=3D=3D=3D=3D=3D=3D=3D=

=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
> mutex=3DMutex.new
>
> t=3DThread.new {
> =A0while true
> =A0 =A0Thread.stop
> =A0 =A0puts "B move..."
> =A0 =A0Thread.main.wakeup
> =A0end
> }
>
> while true
> =A0puts "A move..."
> =A0t.wakeup
> =A0Thread.stop
> end


Since you want to have one thread active at a time only this is not a
case for threads. If at all you might use Fibers:

http://www.rubyinside.com/ruby-fiber...new-concurren=
cy-feature-1769.html
http://www.ruby-doc.org/core-1.9/classes/Fiber.html

The simplest solution is to code interchanges directly:

Actor =3D Struct.new :number do
def alive?; rand(10) !=3D 0 end

def step
printf "Actor %p working...\n", number
end
end

acts =3D Array.new(2) {|i| Actor.new i }

until acts.empty?
acts.delete_if do |a|
a.step
!a.alive?
end
end

Kind regards

robert

--=20
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

 
Reply With Quote
 
 
 
 
jake kaiden
Guest
Posts: n/a
 
      05-13-2011
hi Zd -

how about using a GLib::Timeout instead of threads? threads can gum
up the works if you're not careful...

######
require 'glib2'

repeat = true

GLib::Timeout.add(1000){
p '=>A'
true ? repeat : false
}

GLib::Timeout.add(1000){
p '=>B'
true ? repeat : false
}
######

the true or false at the end of each block tells the timeout whether
to repeat the block or stop - true repeats, false stops. the argument
to the #.add method is the amount of time to wait before repeating.


- j

--
Posted via http://www.ruby-forum.com/.

 
Reply With Quote
 
Zd Yu
Guest
Posts: n/a
 
      05-13-2011
Thanks Robert and Jake. I must use threads. Actually my original problem
is much more complicated and I just simplified it to ask in this forum.

I just found the ConditionVariable class, and it seems it is the key to
implement such cooperation between threads.

Please help review my code below. Let me know if I did anything wrong.

(I have tested the code with both C Ruby and JRuby, and it works well.)
=====================================
require 'thread'

mutex = Mutex.new
resource = ConditionVariable.new
next_one = 'A'

a = Thread.new {
while true
mutex.synchronize {
while next_one != 'A'
resource.wait(mutex)
end
}
puts "A..."
next_one = 'B'
mutex.synchronize {
resource.signal
}
end
}

b = Thread.new {
while true
mutex.synchronize {
while next_one != 'B'
resource.wait(mutex)
end
}
puts "B..."
next_one = 'A'
mutex.synchronize {
resource.signal
}
end
}

a.join
b.join
exit

--
Posted via http://www.ruby-forum.com/.

 
Reply With Quote
 
Robert Klemme
Guest
Posts: n/a
 
      05-13-2011
On Fri, May 13, 2011 at 2:48 PM, Zd Yu <(E-Mail Removed)> wrote:
> Thanks Robert and Jake. I must use threads.


Why?

> Actually my original problem
> is much more complicated and I just simplified it to ask in this forum.


Then apparently you did not abstract the problem properly. Before we
jump to solutions can you explain why you say you must use threads?
What is the real problem you are trying to solve?

> I just found the ConditionVariable class, and it seems it is the key to
> implement such cooperation between threads.
>
> Please help review my code below. Let me know if I did anything wrong.


The whole approach is too complicated for the problem to be solved (see above).

Cheers

robert

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

 
Reply With Quote
 
Zd Yu
Guest
Posts: n/a
 
      05-16-2011
Robert,

I want to use multi-threading + JRuby to achieve better performance.

My problem has a single input file that contains millions of lines. Each
line is the input of a time-consuming computing and will generate an
output result.

What in my mind is:

1. the main thread prepares N working threads, and put them into sleep
state.
2. the main thread open the input file and pass the file object to each
thread[:file]
3. the main thread send a "GO" command to all the working threads
4. each thread works in the below loop:
4.1 lock the mutex associated with the file object, read a line, and
then unlcok. if EOF is encountered, exit from the loop.
4.2 do the very time-consuming computing
4.3 put the result to thread.current[:result]
4.4 signal the main thread to pick up the result
4.5 go to sleep state (waiting for being waken up by the main thread)
5. the main thread works in the below loop:
5.1 go to sleep state until being waken up by one of the working
threads.
5.2 check all the working threads' [:result] and extract them out and
do some aggregation.
5.3 for those threads whose result has been picked, send a signal to
let them proceed with the next line.
6. once all the working threads finish, the main thread output the
aggregated result.

--
Posted via http://www.ruby-forum.com/.

 
Reply With Quote
 
Robert Klemme
Guest
Posts: n/a
 
      05-16-2011
On Mon, May 16, 2011 at 3:19 AM, Zd Yu <(E-Mail Removed)> wrote:
> I want to use multi-threading + JRuby to achieve better performance.
>
> My problem has a single input file that contains millions of lines. Each
> line is the input of a time-consuming computing and will generate an
> output result.
>
> What in my mind is:
>
> 1. the main thread prepares N working threads, and put them into sleep
> =A0 state.
> 2. the main thread open the input file and pass the file object to each
> =A0 thread[:file]
> 3. the main thread send a "GO" command to all the working threads


Did you ever hear of blocking queues?

> 4. each thread works in the below loop:
> =A0 4.1 lock the mutex associated with the file object, read a line, and
> =A0 =A0 =A0 then unlcok. if EOF is encountered, exit from the loop.
> =A0 4.2 do the very time-consuming computing
> =A0 4.3 put the result to thread.current[:result]
> =A0 4.4 signal the main thread to pick up the result
> =A0 4.5 go to sleep state (waiting for being waken up by the main thread)
> 5. the main thread works in the below loop:
> =A0 5.1 go to sleep state until being waken up by one of the working
> =A0 =A0 =A0 threads.
> =A0 5.2 check all the working threads' [:result] and extract them out and
> =A0 =A0 =A0 do some aggregation.
> =A0 5.3 for those threads whose result has been picked, send a signal to
> =A0 =A0 =A0 let them proceed with the next line.
> 6. once all the working threads finish, the main thread output the
> =A0 aggregated result.


This sounds like a very typical application of farmer worker. You
create two queues, one for tasks and one for results. Then you start
a thread which fetches results from the result queue and processes
them. Then you start a number of threads which read from the tasks
queue, process tasks and place results in the result queue. Finally
you use Thread#value to join on the result processor.

# untested
require 'thread'

WORKERS =3D 5

tasks =3D SizedQueue.new WORKERS * 10
results =3D SizedQueue.new WORKERS * 10

agg =3D Thread.new do
state =3D Hash.new 0
th =3D WORKERS

while th > 0
x =3D results.deq

if Thread =3D=3D=3D x
th -=3D 1
else
# aggregate
state[x] +=3D 1
end
end

state
end

workers =3D WORKERS.times.map do
Thread.new do
until (it =3D tasks.deq) =3D=3D tasks
results.enq(process it)
end
results.enq(Thread.current)
end
end

p agg.value

Kind regards

robert

--=20
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

 
Reply With Quote
 
Zd Yu
Guest
Posts: n/a
 
      05-16-2011
Thank you Robert!

I did not know the Queue/SizedQueue classes. They perfectly meet my
requirements.

Thank you again!

--
Posted via http://www.ruby-forum.com/.

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Threads and synchronization Srubys@gmail.com Java 21 06-27-2008 06:17 PM
Synchronization with threads javateamPL@gmail.com Java 4 02-08-2008 03:52 PM
Threads - synchronization jimmie0@wp.pl Java 7 11-26-2006 11:47 PM
When a Java program starts up, several system threads are also started ... Is this why all Java classes have extra synchronization overhead ... Casey Hawthorne Java 1 10-27-2006 09:39 AM
TB View, Threads, Threads with unread The Invisible Man Firefox 1 03-20-2006 02:09 AM



Advertisments