2015-07-29 8 views
6

Qualcuno può farmi sapere cosa c'è di sbagliato nel mio codice qui sotto che implementa il problema produttore-consumatore in python. Sto usando Python 3,4Qualcosa non va nella mia implementazione Producer-Consumer in Python usando gli oggetti condizione?

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

L'output del programma:

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

Poi è rimasto bloccato. Quando chiude il programma, ho ottenuto:

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 

Il Producer sembrava non "nofity" il consumatore. Qualcuno può farmi sapere perché?

Molte grazie in anticipo!

+0

Sembra che tu non rilascia il blocco da nel codice produttore. (Questo deriva dalla mia esperienza con le variabili di condizione C, quindi potrebbe essere diverso in Python). – Xaqq

+1

Per il produttore: in attesa, il blocco verrà rilasciato da cvP.wait(); dopo averlo prodotto con successo, il blocco verrà rilasciato all'uscita di "con cvP", cioè dopo cvC.notify(). Questa è la mia comprensione Sono anche nuovo di Python. –

+0

È passato un po 'di tempo da quando ho seguito il mio corso sul multithreading, ma non dovrei controllare se le dichiarazioni sono invece? Non vedo un motivo per usare "while (len (q) == 0)" su "if (len (q) == 0)" dato che stai già aspettando all'interno del ciclo while. Quando viene notificato/risvegliato, la condizione dovrebbe essere già soddisfatta. – user3085290

risposta

5

Il bloccaggio e lo sbloccaggio vanno bene, ma probabilmente avrete bisogno di specificare 'correre' come destinazione e non 'run()'

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

:-)

Spiegazione: consente di semplificare

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

si può vedere nella traccia dello stack che non è mai andato oltre la linea 47, che è

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

Che è lo stesso di

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

Sei un grande orip! Ha funzionato bene dopo aver rimosso la parentesi. Puoi spiegare un po 'perché questo problema di sintassi causa il problema? Grazie mille! –

+0

@GuohuaLiu - se ha aiutato non dimenticare di accettare la risposta :-D – orip

+0

Non è un problema di sintassi. Aggiornerò la risposta – orip

Problemi correlati