Python - Communication Inter-Thread

Bonjour, futurs sorciers Python !aujourd'hui, nous allons entamer un voyage passionnant dans le monde de la communication inter-thread en Python. Ne vous inquiétez pas si vous êtes nouveau dans la programmation – je serai votre guide amical, expliquant tout étape par étape. Alors, plongeons-y !

Python - Inter-thread Communication

Qu'est-ce que la Communication Inter-Thread ?

Avant d'aller dans les détails, comprenons ce qu'est la communication inter-thread. Imaginez que vous faites partie d'une équipe travaillant sur un grand projet. Vous travaillez tous sur des parties différentes, mais parfois, vous avez besoin de partager des informations ou de coordonner vos efforts. C'est exactement ce que font les threads dans un programme, et la communication inter-thread est comment ils "parlent" les uns aux autres.

L'Objet Événement

Commençons par l'une des manières les plus simples pour les threads de communiquer : l'objet Événement.

Qu'est-ce qu'un Objet Événement ?

Un objet Événement est comme un drapeau qui peut être positionné ou effacé. Les threads peuvent attendre que ce drapeau soit positionné avant de continuer. C'est un peu comme attendre pour un feu vert avant de traverser la rue.

Comment Utiliser l'Objet Événement

Regardons un exemple simple :

import threading
import time

def waiter(event):
print("Serveur : Je attend que l'événement soit défini...")
event.wait()
print("Serveur : L'événement a été défini ! Je peux continuer maintenant.")

def setter(event):
print("Définisseur : Je vais définir l'événement dans 3 secondes...")
time.sleep(3)
event.set()
print("Définisseur : J'ai défini l'événement !")

# Créer un objet Événement
e = threading.Event()

# Créer et démarrer des threads
t1 = threading.Thread(target=waiter, args=(e,))
t2 = threading.Thread(target=setter, args=(e,))

t1.start()
t2.start()

# Attendre que les deux threads se terminent
t1.join()
t2.join()

print("Thread principal : Tout est terminé !")

Analysons cela :

  1. Nous importons le module threading pour créer des threads et le module time pour ajouter des délais.
  2. Nous définissons deux fonctions : waiter et setter.
  3. La fonction waiter attend que l'événement soit défini en utilisant event.wait().
  4. La fonction setter attend 3 secondes (simulant du travail) puis définit l'événement en utilisant event.set().
  5. Nous créons un objet Événement e.
  6. Nous créons deux threads, un pour chaque fonction, en passant l'objet Événement aux deux.
  7. Nous démarrons les deux threads puis utilisons join() pour les attendre.

Lorsque vous exécutez cela, vous verrez le serveur attendre, puis après 3 secondes, le définitisseur défini l'événement, et le serveur continue.

L'Objet Condition

Maintenant, augmentons notre niveau et regardons l'objet Condition. C'est comme le cousin plus sophistiqué de l'objet Événement.

Qu'est-ce qu'un Objet Condition ?

Un objet Condition permet aux threads d'attendre que certaines conditions deviennent vraies. C'est comme attendre qu'une personne spécifique arrive à une fête avant de commencer les jeux.

Comment Utiliser l'Objet Condition

Voici un exemple d'utilisation d'un objet Condition :

import threading
import time
import random

# Ressource partagée
items = []
condition = threading.Condition()

def producer():
global items
for i in range(5):
time.sleep(random.random())  # Simuler des temps de production variables
with condition:
items.append(f"Item {i}")
print(f"Producteur a ajouté Item {i}")
condition.notify()  # Informer le consommateur qu'un élément est disponible

def consumer():
global items
while True:
with condition:
while not items:
print("Consommateur attend...")
condition.wait()
item = items.pop(0)
print(f"Consommateur a enlevé {item}")
time.sleep(random.random())  # Simuler des temps de consommation variables

# Créer et démarrer des threads
producer_thread = threading.Thread(target=producer)
consumer_thread = threading.Thread(target=consumer)

producer_thread.start()
consumer_thread.start()

# Attendre que le producteur se termine
producer_thread.join()

# Arrêter le consommateur (il est dans une boucle infinie)
consumer_thread.daemon = True

Analysons cela :

  1. Nous créons une ressource partagée items et un objet Condition.
  2. La fonction producer ajoute des éléments à la liste et informe le consommateur.
  3. La fonction consumer attend que des éléments soient disponibles, puis les retire et les "consomme".
  4. Nous utilisons with condition: pour acquérir et libérer le verrou de la condition automatiquement.
  5. condition.wait() libère le verrou et attend une notification.
  6. condition.notify() réveille un thread en attente.

Cet exemple démontre une situation classique de producteur-consommateur, où un thread produit des éléments et un autre les consomme.

Comparaison des Objets Événement et Condition

Voici une comparaison rapide des objets Événement et Condition :

Fonctionnalité Événement Condition
But Signalement simple Synchronisation complexe
État Binaire (défini/effacé) Peut avoir plusieurs états
Attente Les threads attendent que l'événement soit défini Les threads attendent des conditions spécifiques
Notification Tous les threads en attente sont notifiés Peut notifier un ou tous les threads en attente
Cas d'utilisation Scénarios "go/no-go" simples Problèmes producteur-consommateur, synchronisation complexe

Conclusion

Félicitations ! Vous venez de faire vos premiers pas dans le monde de la communication inter-thread en Python. Nous avons couvert l'objet Événement pour le signalement simple et l'objet Condition pour des scénarios de synchronisation plus complexes.

N'oubliez pas, comme pour l'apprentissage de toute nouvelle langue, la pratique fait le maître. Essayez d'écrire vos propres programmes utilisant ces objets. Peut-être créez un système de chat simple où les threads représentent des utilisateurs différents, ou simulatez un système de feux tricolores utilisant des événements.

La communication inter-thread peut sembler délicate au début, mais avec du temps et de la pratique, vous orchestrerez des threads comme un maestro dirige une orchestra. Continuez à coder, à apprendre, et surtout, amusez-vous !

Credits: Image by storyset