#!/usr/bin/env python # -*- coding: utf-8 -*- """Un exemple d'utilisation de sémaphores pour synchroniser des tâches. Ce code définit 4 tâches qui devront être exécutées selon la relation de précédence suivante : T1 < T2, T1 < T3, T2 < T4, T3 < T4 Le graphe de précédence pour ces tâches forme donc un diamant : +-----> T2 -----+ | | | \/ T1 T4 | /\ | | +-----> T3 -----+ Ce fichier montre l'utilisation de sémaphores pour assurer l'exécution de ces 4 tâches dans un ordre qui satisfait cette spécification de précédence. Cours « Systèmes d'exploitation ». Sergiu Ivanov """ # La librairie de gestion de fils d'exécution. import threading # Définir 4 sémaphores, un par tâche. t1_finie = threading.Semaphore(); t2_finie = threading.Semaphore(); t3_finie = threading.Semaphore(); t4_finie = threading.Semaphore(); # Le sémaphore ti_finie est relâché à la fin de la tâche Ti. Il est # donc nécessaire de les acquérir tous au début. t1_finie.acquire(); t2_finie.acquire(); t3_finie.acquire(); t4_finie.acquire(); # Nos tâches. # # Chaque tâche commence par vérifier que les tâches dont elle dépend # ont fini leur exécution. À la fin de l'exécution, chaque tâche # relâche le sémaphore qui lui est associé. def t1(): # Tâche initiale, aucune vérification. print("Ceci est la tâche T1") t1_finie.release(); def t2(): # Cette opération sera bloquée si le sémaphore t1_finie n'est pas # encore relâché. t1_finie.acquire(); # Si nous sommes arrivés ici, nous savons que le sémaphore # t1_finie a été relâché. Ne le gardons pas pris, relâchons-le # pour que les autres puissent avoir les signal. t1_finie.release(); print("Ceci est la tâche T2") t2_finie.release(); def t3(): t1_finie.acquire(); t1_finie.release(); print("Ceci est la tâche T3") t3_finie.release(); def t4(): # La tâche T4 dépend des tâches T3 et T4 ; on vérifiera donc deux # sémaphores. t2_finie.acquire(); t2_finie.release(); t3_finie.acquire(); t3_finie.release(); print("Ceci est la tâche T4") t4_finie.release(); # Créer un objet Thread (fil d'exécution) pour chacune de nos tâches. # # Les fils ne sont pas encore lancés. t1_thread = threading.Thread(target = t1) t2_thread = threading.Thread(target = t2) t3_thread = threading.Thread(target = t3) t4_thread = threading.Thread(target = t4) # Lancer les fils d'exécution dans un ordre quelconque, pas # nécessairement correspondant au graphe de précédence exigé. t4_thread.start() t3_thread.start() t2_thread.start() t1_thread.start()