Thread deadlock problem

I made the following test:

···

#-------------------------------------------------------------------
require 'thread'

mutex = Mutex.new
c_produce = ConditionVariable.new
c_consume = ConditionVariable.new
full = false
t1 = Thread.new do
  while true
   mutex.synchronize do
    c_produce.wait mutex while full
    print 'F'
    full = true
    c_consume.signal
   end
         #sleep 0.001
  end
end
t2 = Thread.new do
  while true
   mutex.synchronize do
    c_consume.wait mutex while !full
    print '.'
    full = false
    c_produce.signal
   end
  end
end
t1.join
t2.join
#-------------------------------------------------------------------

This should be a classic producer/consumer problem solution. The
output:

F.F.F.F.F.F.F.F.F.F.F.F.F.F.F.F.F.F.F.F.F.F.F.F.F.F.F.F.F.F.F.deadlock
0x2b68300: sleep:- - c:/ruby/projects/threads2.rb:9
deadlock 0x27bc74c: sleep:J(0x2b68300) (main) - c:/ruby/projects/
threads2.rb:27
deadlock 0x2b68274: sleep:- - c:/ruby/projects/threads2.rb:20
c:/ruby/projects/threads2.rb:20: Thread(0x2b68274): deadlock (fatal)

What is wrong with the code?

ruby -v

ruby 1.8.6 (2007-03-13 patchlevel 0) [i386-mswin32]

Also, uncommenting a sleep from above makes the deadlocks disappear
and everything works rather fine - is this just a matter of tweaking
the probability? It ran for quite a long time (several minutes),
that's why I doubt this, but hey - I just might be completely wrong.
Any ideas?

it seems like you are making if very hard on yourself. why not something like this:

cfp:~ > cat a.rb
require 'thread'

q = SizedQueue.new 42

producer = Thread.new do
   loop do
     q.push Time.now.to_f
   end
end

consumer = Thread.new do
   loop do
     p(( data = q.pop ))
   end
end

producer.join
consumer.join

??

if you really want to roll your own stuff check out the code in thread.rb - the Queue and SizedQueue classes are basically the code you are writing above.

cheers.

a @ http://drawohara.com/

···

On Sep 10, 2007, at 9:35 PM, wimxa@yahoo.com wrote:

require 'thread'

mutex = Mutex.new
c_produce = ConditionVariable.new
c_consume = ConditionVariable.new
full = false
t1 = Thread.new do
  while true
   mutex.synchronize do
    c_produce.wait mutex while full
    print 'F'
    full = true
    c_consume.signal
   end
         #sleep 0.001
  end
end
t2 = Thread.new do
  while true
   mutex.synchronize do
    c_consume.wait mutex while !full
    print '.'
    full = false
    c_produce.signal
   end
  end
end
t1.join
t2.join

--
we can deny everything, except that we have the possibility of being better. simply reflect on that.
h.h. the 14th dalai lama

What version of Ruby are you using ? The thread implementation has been
broken in many ways since 1.8.6, so it can be the problem

(I have a patched ruby 1.8.6 here with some fixes and it works fine)

···

--
Sylvain Joyeux

I think you at least need a newer patchlevel of 1.8.6; IIRC, there are
bugs in the mutex implementation that shipped with 1.8.6p0.

-mental

···

On Tue, 11 Sep 2007 12:35:08 +0900, wimxa@yahoo.com wrote:

ruby 1.8.6 (2007-03-13 patchlevel 0) [i386-mswin32]

Also, uncommenting a sleep from above makes the deadlocks disappear
and everything works rather fine - is this just a matter of tweaking
the probability? It ran for quite a long time (several minutes),
that's why I doubt this, but hey

@ara

it seems like you are making if very hard on yourself.

No, this is just a test. I have another problem requiring the
synchronization. It is not working, so I made this test to see what is
I am doing wrong. It seems that it is not a problem with the other
code, but the part of the code that is similar to what I have made in
the above test. However, thanks for the pointers - I will take a look
at them and I might just find an answer.

@Sylvain

What version of Ruby are you using ?

I have posted the output of

ruby -v

which is:

ruby 1.8.6 (2007-03-13 patchlevel 0) [i386-mswin32]

Do you need some more info (and how can I obtain it)?

Also, is there some good documentation about multi-threading in ruby,
especially the synchronization part? I have looked at some tutorials
(e.g. Programming Ruby: The Pragmatic Programmer's Guide), but they
are sparse on this topic (just a few examples, not even near to what I
need). Any others?

Thanks, that worked. I just downloaded patch 36 and it worked fine.
*sigh*

···

On Sep 11, 12:59 pm, MenTaLguY <men...@rydia.net> wrote:

On Tue, 11 Sep 2007 12:35:08 +0900, wi...@yahoo.com wrote:
> ruby 1.8.6 (2007-03-13 patchlevel 0) [i386-mswin32]

> Also, uncommenting a sleep from above makes the deadlocks disappear
> and everything works rather fine - is this just a matter of tweaking
> the probability? It ran for quite a long time (several minutes),
> that's why I doubt this, but hey

I think you at least need a newer patchlevel of 1.8.6; IIRC, there are
bugs in the mutex implementation that shipped with 1.8.6p0.

-mental