1. Le Dîner des Philosophes
1.1. Le Problème
On veut implémenter une solution au Dîner des Philosophes. Pour
cela, on va créer des processus enfants qui exécutent la fonction
philo(fg,fd)
suivante, où les fourchettes gauche (fg
) et droite (fd
) sont
des multiprocessing.Lock
.
T = 2 def prendre(f): print(f"{pid} {id}: Je vais prendre {f.id}") f.acquire() # Bloquant print(f"{pid} {id}: J'ai pris {f.id}") def reposer(f): print(f"{pid} {id}: Je repose {f.id}") f.release() def manger(): print(f"{pid} {id}: Je mange...") time.sleep(randrange(T)) def philo(fg,fd): for r in range(3): # time.sleep(randrange(T)) prendre(fg) # time.sleep(randrange(T)) prendre(fd) manger() reposer(fg) reposer(fd) print(f"{pid} {id}: J'ai fini !") print(f"{pid} {id}: Fini")
Créer un processus parent qui
- crée
NB
fourchettes (avecmultiprocessing.Lock()
), leur affecte unid
pour pouvoir les nommer facilement; - crée
NB
processus enfants et leur fait exécuterphilo(fg,fd)
avec les fourchettes gauche (fg
) et droite (fd
) - attend la fin des
NB
processus enfants
1.2. Interblocage
Faire plusieurs exécutions du code précédent avec NB=5
.
Arrive-t-on à éviter l’interblocage ? Que
se passe-t-t-il si l’on décommente les deux lignes sleep
? Pourquoi ?
Que se passe-t-il si l’on remplace le for r in range(3):
par while True:
?
1.3. Solution
Modifier le parent pour qu’il coordonne, ie ordonnance, les
enfants afin que aucun interblocage ne se produise. Chaque enfant sera
relié au parent par un tube anonyme sur lequel il attendra
l’indication qu’il peut commencer à acquérir les fourchettes. Lorsque
l’enfant a fini, il envoie un signal SIGUSR1
au parent pour
signaler qu’il a fini.
On pourra utiliser un ordonnancement de type “tourniquet”.
Que peut-on dire de l’efficacité de cette solution en terme de parallélisme ?
Pouvez-vous proposer une solution plus efficace si NB=6
?