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)) |
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.
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 :