64 lines
3.6 KiB
Markdown
64 lines
3.6 KiB
Markdown
# Exclusion mutuelle et synchronisation élémentaire
|
||
|
||
## Objectifs
|
||
|
||
- réfléchir sur les protocoles de base de gestion de la cohérence par exclusion mutuelle
|
||
- première approche de la synchronisation de processus au travers de l'utilisation d'un
|
||
mécanisme élémentaire de verrouillage/déverrouillage
|
||
|
||
## Préparation
|
||
|
||
### Les verrous Java (complément)
|
||
|
||
**Au sein d'un bloc `synchronized`** contrôlé par un objet `unObj`, il est possible de
|
||
réaliser une synchronisation élémentaire au moyen des deux méthodes suivantes, fournies par
|
||
tout objet :
|
||
|
||
- `unObj.wait()` libère l’accès exclusif à `unObj` et bloque l’activité appelante
|
||
en attente d’un réveil via une opération
|
||
- `unObj.notify()` ou `unObj.notifyAll()` qui réveille une (ou toutes les) activité(s)
|
||
bloquées sur `unObj.wait()`
|
||
- Remarques 1. les activités réveillées par `notify` sont mises en attente du verrou et ne poursuivent
|
||
effectivement qu'une fois celui-ci obtenu 2. une activité en bloquée sur `wait` _peut_ être réveillée spontanément...
|
||
Il est donc conseillé que l'attente soit gardée par une condition logique, et que cette
|
||
condition logique soit évaluée dans une boucle `while`, selon le schéma suivant :
|
||
`synchronized (obj) { while ( condition invalide ) { unObjbj.wait(); } <opérations à réaliser une fois la condition vérifiée > }`
|
||
|
||
## Exercices
|
||
|
||
**Note** : Pour les besoins de ce TP, _la synchronisation des exercices qui suivent
|
||
doit être traitée en utilisant des **verrous**, à l'exclusion de tout autre outil
|
||
(sémaphores, moniteurs...)_. (Ces outils conviendraient, mais ce n'est pas l'objet de ces exercices.)
|
||
|
||
### Exclusion mutuelle
|
||
|
||
1. La classe `Peterson` fournie dans l'archive propose une implémentation du protocole
|
||
d'exclusion mutuelle de Peterson vu en cours. Vérifiez et complétez éventuellement cette
|
||
implémentation.
|
||
|
||
2. L'ordre des deux premières affectations de la méthode entrer() (lignes 29 et 30 :
|
||
`Peterson.demande[id] = true;` et `Peterson.tour = di ;`) est-il important ? Pourquoi ?
|
||
|
||
3) La classe `java.util.concurrent.atomic.AtomicBoolean` propose une implantation
|
||
logicielle de primitives de type TestAndSet, CompareAndSwap... - Implanter le protocole d'exclusion mutuelle pour N processus utilisant la primitive TestAndSet
|
||
présentée en cours (planche 23) - Réaliser une version vivace du protocole, garantissant que toute demande d'entrée
|
||
en section critique finira par être servie. - Comparer les performances des deux versions, entre elles et par rapport à une
|
||
version utilisant un bloc `synchronized` pour assurer l'exclusion mutuelle. - Comparer, pour 2 processus, ces versions à une version utilisant le protocole de Peterson
|
||
|
||
### Schéma producteurs consommateurs
|
||
|
||
4. Compléter la classe `TamponBorné` fournie, qui ne comporte aucune synchronisation, afin de
|
||
gérer convenablement les accès concurrents.
|
||
|
||
- seules les méthodes `déposer` et `retirer` de la classe `TamponBorné` sont à modifier. Les
|
||
parties du code où l'on suggère d'intervenir sont signalées par un commentaire `//*** A compléter`
|
||
- le test intégré à l'application est conçu pour vérifier le comportement attendu suivant :
|
||
|
||
* initialement, les consommateurs doivent attendre, car le tampon est vide
|
||
* les consommateurs retirent des entiers différents, dans l'ordre croissant,
|
||
sans trous dans la numérotation
|
||
* progressivement, de plus en plus de producteurs doivent attendre
|
||
|
||
Vous pouvez commencer par exécuter le code fourni sans synchronisation, et constater qu'il
|
||
ne produit pas vraiment le comportement attendu...
|