使用条件对象在Python中的Producer-Consumer实现中有什么问题吗?

Guo*_*Liu 6 python multithreading

有人能告诉我下面的代码中有什么问题,它在python中实现了生产者 - 消费者问题.我使用的是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()
Run Code Online (Sandbox Code Playgroud)

程序输出:

Produced  0
Produced  1
Produced  2
Produced  3
Queue is full and size =  4
Run Code Online (Sandbox Code Playgroud)

然后它卡住了.终止程序时,我得到:

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
Run Code Online (Sandbox Code Playgroud)

制片人似乎不是消费者的"nofity".有人能让我知道为什么吗?

提前谢谢了!

ori*_*rip 5

锁定和解锁都很好,但您可能希望将"run"指定为目标而不是"run()"

pThread = Thread( target=p.run, args=())
cThread = Thread( target=c.run, args=())
Run Code Online (Sandbox Code Playgroud)

:-)

说明:让我们简化

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())
Run Code Online (Sandbox Code Playgroud)

您可以在堆栈跟踪中看到它从未超出第47行,即

pThread = Thread( target=p.run(), args=())
Run Code Online (Sandbox Code Playgroud)

哪个是一样的

x = p.run()
pThread = Thread(x, args=())
Run Code Online (Sandbox Code Playgroud)