2015-07-29 9 views
6

Czy ktoś może mi powiedzieć, co jest nie tak w moim poniższym kodzie, który implementuje problem producent-konsument w python. Używam Python 3.4Coś nie tak w mojej implementacji Producent-Konsument w Pythonie przy użyciu obiektów warunkowych?

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() 

Wyjście Program:

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

Potem utknąłem. Po zakończeniu programu otrzymałem:

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 

Producent nie wydawał się "nofity" konsumentem. Czy ktoś może mi powiedzieć, dlaczego?

Wielkie dzięki z góry!

+0

Wygląda jak nigdy zwolnić blokadę od kod producenta. (To jest z mojego doświadczenia ze zmiennymi warunkowymi C, więc może być inaczej w Pythonie). – Xaqq

+1

Dla producenta: w momencie oczekiwania blokada zostanie zwolniona przez cvP.wait(); po pomyślnym wytworzeniu blokada zostanie zwolniona przy wyjściu "z cvP", tj. po cvC.notify(). To jest moje zrozumienie. Jestem również nowy w Pythonie. –

+0

Minęło trochę czasu, odkąd wziąłem udział w kursie wielowątkowego systemu operacyjnego, ale czy nie powinno się sprawdzać, czy zamiast tego są instrukcje? Nie widzę powodu, aby używać "while (len (q) == 0)" powyżej "if (len (q) == 0)", ponieważ już czekałeś wewnątrz pętli while. Kiedy zostanie powiadomiony/obudzony, warunek powinien już być spełniony. – user3085290

Odpowiedz

5

Blokowanie i odblokowywanie są w porządku, ale prawdopodobnie chcesz, aby określić 'Uruchom' jako cel, a nie 'run()'

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

:-)

Objaśnienie: pozwala uprościć

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()) 

można zobaczyć w ślad stosu, że nigdy nie wykraczały poza linią 47, która jest

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

który jest taki sam jak

x = p.run() 
pThread = Thread(x, args=()) 
+0

Jesteś świetny orip! Po usunięciu nawiasu zadziałało dobrze. Czy możesz wyjaśnić, dlaczego ten problem z składnią powoduje bieżący problem? Dziękuję bardzo! –

+0

@GuohuaLiu - jeśli pomogło, nie zapomnij przyjąć odpowiedzi :-D – orip

+0

Nie jest to problem z syntaktą. Zaktualizuję odpowiedź. – orip

Powiązane problemy