0

Le code suivant est de Raymond's Pycon keynotes on cuncurrency, excellente présentation. Il est un peu long, donc je vais commencer par la question:synchronisation de thread utilisant des files d'attente de messages n'est pas en ordre

  • Si messages sont additionnés à une file d'attente , et les deux devraient être imprimé avant qu'un thread est considéré comme fait, comment viennent plus ils sont imprimé ébranlé? L'ajout d'un délai de 100 ms entre l'initialisation du thread résout ceci, et la sortie est comme prévu.

-

import Queue, time 

counter_queue = Queue.Queue() 
counter = 0 

def counter_manager(): 
    # I have EXCLUSIVE rights to update the counter variable 
    global counter 

    while True: 
     increment = counter_queue.get() 
     counter += 1 
     print_queue.put(['The count is {}\n'.format(counter), 
         '----------\n']) 
     counter_queue.task_done() 

t = threading.Thread(target=counter_manager) 
t.daemon = True 
t.start() 
del t 


print_queue = Queue.Queue() 

def print_manager(): 
    # I have EXCLUSIVE rights to call the print keyword 
    while True: 
     job = print_queue.get() 
     for line in job: 
      print line 
     print_queue.task_done() 

t = threading.Thread(target=print_manager) 
t.daemon = True 
t.start() 
del t 

def worker_threads(): 
    counter_queue.put(1) 

print_queue.put(['Starting up.. with message queues']) 
worker_threads = [] 
for i in range(10): 
    t = threading.Thread(target=worker) 
    worker_threads.append(t) 
    t.start() 
    # time.sleep(0.1) 
for t in worker_threads: 
    t.join() 

counter_queue.join() 
print_queue.put(['Finishing up']) 
print_queue.join() 

Il utilise counter_manager et print_queue en tant que daemons pour recevoir les messages des threads de travail, et les exécuter de manière séquentielle. Si je comprends bien, cela devrait préserver l'ordre d'exécution. Cependant, j'obtiens la sortie suivante:

Starting up.. with message queues 
The couns is 1The couns is 2 

-------------------- 

The couns is 3 
----------The couns is 4 
The couns is 5 
The couns is 6 
---------- 
---------- 
---------- 
The couns is 7 

----------The couns is 8 

The couns is 9---------- 

----------The couns is 10 

---------- 
Finishing up 

Le compteur est incrémenté correctement, les messages d'impression sont toujours ébranlés.

Si je décommenter la déclaration du sommeil, l'initialisation des threads est retardée par 100ms et la sortie est correcte

Starting up.. with message queues 
The couns is 1 
---------- 
The couns is 2 
---------- 
The couns is 3 
---------- 
The couns is 4 
---------- 
The couns is 5 
---------- 
The couns is 6 
---------- 
The couns is 7 
---------- 
The couns is 8 
---------- 
The couns is 9 
---------- 
The couns is 10 
---------- 
Finishing up 

En utilisant les files d'attente, les impressions doivent être en ordre. N'est-ce pas?


Le code des travailleurs

def worker(): 
    global counter 

    counter += 1 
    print 'The couns is {}'.format(counter) # read the var (race cond.) 
    print '----------' 

Répondre

2

Je n'a pas pu reproduire le problème. Pour l'exécuter, j'ai ajouté une importation threading et renommé la fonction worker_threads en worker.

La sortie a "couns" mais votre code indique "count". Pouvez-vous vérifier que la sortie et le code que vous fournissez coïncident?

Votre sortie semble s'entrelacer uniquement au niveau de la ligne.

Je me demande si une version antérieure du code avait deux .put s différents (non atomiques) en counter_manager qui ont ensuite été combinés en un seul .put avec plusieurs lignes?

+0

Wow, merci! J'ai défini une fonction de travail le fichier sur une partie différente et l'utilisais. J'ai mis par erreur 'worker' au lieu de' worker_threads' – Vinny

+0

@Vinny Pouvez-vous inclure la définition de 'worker' alors? 'worker_threads' ne fonctionnera pas comme la' target 'Thread' parce que 'worker_threads' est aussi défini comme une liste. – ryachza

+0

Je l'ai ajouté. La méthode de travail n'est pas atmoic. Il est utilisé pour créer une condition de concurrence, et le résoudre en utilisant les files d'attente de messages – Vinny