work-site/content/courses/os-ueve/semaphores.py

112 lines
2.7 KiB
Python

#!/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 <sergiu.ivanov@univ-evry.fr>
"""
# 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()