2010-09-17 2 views
2

J'ai le code "consommateur" suivant:python - comment faire "condition.wait" et "condition.notifyAll" travail

.... 

    while 1: 

     time.sleep(self.sleeptime) 

     cond.acquire() #acquire the lock 
     print currentThread(), "lock acquired" 

     while itemq.isEmpty(): 
      cond.wait() 

     itemq.consume() 
     print currentThread(),"Consumed One Item" 
     cond.release() 

Et le code du producteur suivant:

....  
while 1 : 


      cond.acquire() #acquire the lock 
      print currentThread(), "lock acquired" 
      print currentThread(),"Produced One Item" 
      itemq.produce() 
      cond.notifyAll() 
      cond.release() 

      time.sleep(self.sleeptime) 

I dirige le programme avec 1 producteur et 2 consommateurs. Je ne sais pas à quoi s'attendre. Le producteur appelle "notifyAll()", donc je m'attends à ce que les deux consommateurs se réveillent de leur "attente". Je vois qu'en effet les deux consommateurs acquièrent la serrure, mais seul le premier qui a acquis la serrure arrive à consommer l'article. Quelqu'un pourrait-il me dire comment fonctionne la commande "wait"? Si les deux threads obtiennent le "notifyAll", comment est-ce qu'un seul peut consommer?

Merci, Li

+0

Astuce: vous devriez accepter plus de réponses pour améliorer vos chances d'en obtenir. –

+0

Je ne savais même pas qu'il existe une telle possibilité :) – user429400

+0

Merci dieu son reversable. Je pensais que je serais condamné pour toujours :) – user429400

Répondre

0

La clé est dans la boucle autour de l'attente:

while itemq.isEmpty(): 
     cond.wait() 

cond.wait() est mis en œuvre quelque chose comme ceci (exemple seulement):

def wait(): 
    cond.release() 
    wait for notify 
    cond.aquire() 

Ainsi, un seul sort consommateur le ' attendre la fonction à la fois grâce à la serrure. Le premier consommateur à quitter la fonction d'attente détecte que itemq.isEmpty() == false et continue à consommer l'élément. Ils rentrent ensuite dans la fonction d'attente et relâchent le verrou.Le deuxième consommateur se termine, détecte que itemq.isEmpty() == true à nouveau, et rentre immédiatement dans wait()).

2

Je pense que the docs sont très claires:

La méthode wait() libère le verrou, puis bloque jusqu'à ce qu'il soit réveillé par un notify() ou notifyAll() appelle la même variable de condition dans un autre thread . Une fois éveillé, il ré-acquiert le verrou et revient. Il est également possible de spécifier un délai d'expiration.

et:

Note: notify() et notifyAll() méthodes ne libèrent pas la serrure; ce signifie que le fil ou les fils éveilla ne reviendront pas à leur attente () appelez immédiatement, mais seulement quand le thread qui a appelé notify() ou notifyAll() enfin renonce à la propriété du lock.ownership de la serrure .

Un seul thread peut avoir le verrou à tout moment, bien sûr: c'est le noyau but d'avoir un verrou en premier lieu, après tout!

Ainsi, OIEau, notifyAll met tous les threads en attente dans un état prêt à courir, et attendre intrinsèquement tout pour acquérir à nouveau le verrou afin qu'ils puissent procéder: une fois le notifiant libère le verrou, un des fils en attente de acquérir ce verrou l'acquiert (les autres, le cas échéant, attendent toujours que le verrou soit relâché, bien sûr, de sorte qu'un seul thread ait le verrou à un moment donné).

+0

Merci :) J'ai remarqué que le premier qui acquiert la serrure gagne. Est-ce que c'est mis en place comme une file d'attente ou quelque chose? – user429400

+0

@user, détail de l'implémentation (non documenté, et peut changer à tout moment pour une raison quelconque ou sans raison). Si vous êtes curieux d'une version spécifique, consultez le code source Python, par exemple. ici: http://xmpp.org/rfcs/rfc3921.html#sub lignes 150 et suivantes (y compris les routines internes utilisées pour acquérir/restaurer et libérer/enregistrer). –

+0

THanks :) Je pense que je n'ai pas compris que si un thread n'a pas gagné le verrou, il attendra un autre notify() ... Je pensais qu'une fois éveillé, il n'attendrait que le verrou, et n'attendra pas une autre notification() ... – user429400

Questions connexes