Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Anything wrong in my Producer-Consumer implementation in Python using condition objects?

Can someone let me know what is wrong in my code below that implements the producer-consumer problem in python. I am using Python 3.4

import threading
from threading import Thread
from collections import deque
import time

maxSize = 4    # maximum size of the queue
q = deque([])
cur = 0    # current value to push into the queue

lk = threading.Lock()
cvP = threading.Condition(lk)    # condition object for consumer
cvC = threading.Condition(lk)    # condition object for producer

class Producer:
    def run(self):
        global maxSize, q, cur
        while True:
            with cvP:
                while len(q) >= maxSize:
                    print( "Queue is full and size = ", len(q) )
                    cvC.notify()   # notify the Consumer
                    cvP.wait()    # put Producer to wait

                q.append(cur)
                print("Produced ", cur)
                cur = cur + 1
                cvC.notify()    # notify the Consumer


class Consumer:
    def run(self):
        global maxSize, q, cur
        while True:
            with cvC:
                while len(q) == 0:
                    print( "Queue is empty and size = ", len(q) )
                    cvP.notify()  # notify the Producer
                    cvC.wait()    # put Consumer to wait

                x = q.popleft()
                print("Consumed ", x)
                time.sleep(1)
                cvP.notify()    # notify the Producer

p = Producer()
c = Consumer()
pThread = Thread( target=p.run(), args=())
cThread = Thread( target=c.run(), args=())
pThread.start()
cThread.start()
pThread.join()
cThread.join()

The program output:

Produced  0
Produced  1
Produced  2
Produced  3
Queue is full and size =  4

Then it got stuck. When terminating the program, I got:

Traceback (most recent call last):
  File "path/t.py", line 47, in <module>
    pThread = Thread( target=p.run(), args=())
  File "path/t.py", line 22, in run
    cvP.wait()
  File "/usr/lib/python3.4/threading.py", line 289, in wait
    waiter.acquire()
KeyboardInterrupt

The Producer seemed not "nofity" the consumer. Can someone let me know why?

Many thanks in advance!

like image 201
Guohua Liu Avatar asked Jul 29 '15 16:07

Guohua Liu


1 Answers

The locking and unlocking are fine, but you probably want to specify 'run' as the target and not 'run()'

pThread = Thread( target=p.run, args=())
cThread = Thread( target=c.run, args=())

:-)

Explanation: lets simplify

def foo():
  # ..

# Foo will run on a new thread
Thread(target=foo)

# foo() is run before the thread is created, and its return
# value is the target for the Thread call.
Thread(target=foo())

You can see in the stack trace that it never went beyond line 47, which is

pThread = Thread( target=p.run(), args=())

Which is the same as

x = p.run()
pThread = Thread(x, args=())
like image 148
orip Avatar answered Oct 23 '22 04:10

orip