Rechercher
 

Améliorations / Corrections

Vous avez des améliorations (ou des corrections) à proposer pour ce document : je vous remerçie par avance de m'en faire part, cela m'aide à améliorer le site.

Emplacement :

Description des améliorations :

Manipulation de threads et accès concurrents

L'exemple de code Python ci-dessous montre deux aspects. Premièrement, comment démarrer un thread en Python. Et second point, comment synchroniser des accès concurrents.

Pour créer un nouveau thread, veuillez coder une classe dérivant de threading.Thread, veuillez y redéfinir une méthode run (c'est elle qui servira de point d'entrée au nouveau thread), ensuite, instanciez un objet à partir de cette classe, puis enfin invoquez-y la méthode start. Dans l'exemple suivant, dix nouveaux threads sont démarrés et chacun d'entre eux va essayer d'incrémenter, cent mille fois, l'attribut statique counter. Au final, on devrait normalement avoir 1 000 000 dans le compteur.

Un attribut statique est partagé par toutes les instances de la classe. Donc, dans notre cas, les dix threads incrémenteront en même temps cette zone mémoire. Il est donc nécessaire de verrouiller les accès en écriture sur cet attribut. C'est ce qui est fait grace à l'instance __lock de la classe threading.Lock. Je vous invite à lancer le programme avec, puis sans, les trois lignes de codes suivis du commentaire # Try to remove pour constater les résultats produits avec ou sans le verrouillage.

 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
 10 
 11 
 12 
 13 
 14 
 15 
 16 
 17 
 18 
 19 
 20 
 21 
 22 
 23 
 24 
 25 
 26 
 27 
 28 
 29 
 30 
 31 
 32 
 33 
 34 
 35 
 36 
 37 
 38 
 39 
 40 
 41 
#!/usr/bin/python3
# -*- coding: utf-8 -*- 

from threading import Thread, Lock

class DemoThread( Thread ):
    
    counter = 0
    __lock = Lock()         # Try to remove
    
    
    def __init__(self, name):
        Thread.__init__(self, name=name)
        
    def run(self):
        
        for i in range(100000):
            try:
                DemoThread.__lock.acquire()         # Try to remove
                DemoThread.counter += 1
            finally:
                DemoThread.__lock.release()         # Try to remove

        print(self.name + " finished!")
 
 
# Démarrage de 10 threads 
threads = []
for i in range(10):            
    thread = DemoThread("Thread " + str(i))
    thread.start()
    threads.append(thread)

print("All threads are started")

# On attend que les 10 threads aient terminés.
for thread in threads:
    thread.join()
    
# On vérifie si l'on a bien 1 000 000 dans DemoThread.counter
print("counter == " + str(DemoThread.counter))
Exemple de manipulation de threads et gestion des accès concurrents
l'instruction try finally est utilisée pour garantir, quelque soit l'issue finale de la méthode run (même en cas de déclenchement d'exception), que le verrou sera bien relaché. Sans quoi, des « dead locks » pourraient arriver dans certains cas.