Deadlock producer consumer

Hi
I make the following test

···

#--------------------------------------------------
ProducerQueue = Containers::PriorityQueue.new
ConsumerQueue = Containers::Queue.new

mutex = Mutex.new
access = ConditionVariable.new

initialize ProducerQueue

producer = Thread.new do
loop do
  mutex.synchronize {
    while ProducerQueue.empty? do access.wait(mutex) end

    ProducerQueue.pop
    somework
    ConsumerQueue.push(result)
    access.signal
  }
end
end
consumer = Thread.new do
loop do
  mutex.synchronize {
    while ConsumerQueue.empty? do access.wait(mutex) end

    page = ConsumerQueue.pop()
    somework
    ProducerQueue.push(result)
    access.signal

  }
end
end

consumer.join
producer.join
#----------------------------------------------------------

I keep having deadlock when executing it
What is wrong with the code? I think may be I have to add an other
ConditionVariable, the problem is the producer and the consumer use the
two queues

Any Ideas

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

When you use mutex.synchronize, it's going to lock to mutex. When you call access.wait(), it releases that same mutex and waits for the mutex to be unlocked. But you have already locked it, and it should/can not unlock until after the block is finished. I'm not even sure what the behavior is here, but it's unlikely to work as you might expect.

-Justin

···

On 10/14/2011 05:42 PM, rubix Rubix wrote:

Hi
I make the following test

#--------------------------------------------------
  ProducerQueue = Containers::PriorityQueue.new
  ConsumerQueue = Containers::Queue.new

  mutex = Mutex.new
  access = ConditionVariable.new

  initialize ProducerQueue

producer = Thread.new do
loop do
   mutex.synchronize {
     while ProducerQueue.empty? do access.wait(mutex) end

     ProducerQueue.pop
     somework
     ConsumerQueue.push(result)
     access.signal
   }
end
consumer = Thread.new do
loop do
   mutex.synchronize {
     while ConsumerQueue.empty? do access.wait(mutex) end

     page = ConsumerQueue.pop()
     somework
     ProducerQueue.push(result)
     access.signal

   }
end

consumer.join
producer.join
#----------------------------------------------------------

I keep having deadlock when executing it
What is wrong with the code? I think may be I have to add an other
ConditionVariable, the problem is the producer and the consumer use the
two queues

Any Ideas

Is there any reason you're not using Queue?

queue = Queue.new

consumer = Thread.start do
  loop do
    queue.enq produce_value
  end
end

producer = Thread.start do
  loop do
    consume_value queue.deq
  end
end

···

On Oct 14, 2011, at 5:42 PM, rubix Rubix wrote:

I keep having deadlock when executing it

What is wrong with the code? I think may be I have to add an other
ConditionVariable, the problem is the producer and the consumer use the
two queues

I tried simple Queue and it doesn't work too
because I think it a circular wait, the consumer consume from a queue
but produce new data and push them to the other queue
the producer make the same thing too
and i think that's why I have deadlock but I don't know how to solve the
problem

···

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

thanks Sean,

I have a version with PriorityQueue from algorithms gem to pop the item
with the highest priority first but I had the problem of deadlock
but I tried today before your post a version with two standard queue but
it doesn't work too,
I don't know why you add the lines :

···

---------------
item[:consumer] += 1
----------------
and
----------------------
# start things off
producer_queue.push({ :producer => 0, :consumer => 0})
# either will work
#consumer_queue.push({ :producer => 0, :consumer => 0})
------------------------------
I'll try this version and see if it works

regards,

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

I still have the deadlock problem
but I have some exceptions in somework of the produced values,
is unhandeled exception can be a cause of the deadlock?

···

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

Is this the kind of behaviour you're looking for?

require 'thread'

producer_queue = Queue.new
consumer_queue = Queue.new

def log(*a)
  STDERR.print a.inspect + "\n"
end

producer = Thread.start do
  loop do
    log :producer, :pop
    item = producer_queue.pop
    log :producer, :item, item
    item[:producer] += 1
    log :producer, :push, item
    consumer_queue.push(item)
  end
end

consumer = Thread.start do
  loop do
    log :consumer, :pop
    item = consumer_queue.pop
    log :consumer, :item, item
    item[:consumer] += 1
    log :consumer, :push, item
    producer_queue.push(item)
  end
end

# start things off
producer_queue.push({ :producer => 0, :consumer => 0})
# either will work
#consumer_queue.push({ :producer => 0, :consumer => 0})

consumer.join
producer.join

Regards,
Sean

···

On Sat, Oct 15, 2011 at 3:26 PM, rubix Rubix <aggouni2002@yahoo.fr> wrote:

I tried simple Queue and it doesn't work too
because I think it a circular wait, the consumer consume from a queue
but produce new data and push them to the other queue
the producer make the same thing too
and i think that's why I have deadlock but I don't know how to solve the
problem

thanks Sean,

I have a version with PriorityQueue from algorithms gem to pop the item
with the highest priority first but I had the problem of deadlock
but I tried today before your post a version with two standard queue but
it doesn't work too,
I don't know why you add the lines :
---------------
item[:consumer] += 1
----------------
and

That's just to show that the producer and consumer threads are
processing the item as it gets passed back and forth.

----------------------
# start things off
producer_queue.push({ :producer => 0, :consumer => 0})
# either will work
#consumer_queue.push({ :producer => 0, :consumer => 0})
------------------------------

You need at least one item in either queue to get the ball rolling.

Regards,
Sean

···

On Sat, Oct 15, 2011 at 9:52 PM, rubix Rubix <aggouni2002@yahoo.fr> wrote:

It can stop its thread, so yes.

-- Matma Rex

···

2011/10/16 rubix Rubix <aggouni2002@yahoo.fr>:

is unhandeled exception can be a cause of the deadlock?