:: Enseignements :: Master :: M1 :: 2017-2018 :: Java Avancé ::
[LOGO]

Rendez-vous et synchronization


Exercice 1 - A vos chronometres

On cherche à savoir combien d'itérations d'une boucle on peut faire en 100 millisecondes. Un de vos collègues a produit le code suivant:

  1. Sans exécuter le code, que fait ce programme ?
  2. Vérifier, en exécutant le programme (plusieurs fois), si vous avez vu juste.
  3. Comment doit-on corriger le problème ?
    Modifier la classe Bogus en conséquence.
  4. On cherche maintenant a accélérer le code de Bogus en utilisant le mot clé volatile au lieu des blocs synchronized.
    Créer une classe BogusVolatile qui n'utilise pas de bloc synchronized.
    Comment appelle-t-on les implantations qui n'ont ni blocs synchronized, ni lock ?

Exercice 2 - Generateur pseudo-aléatoire lock-free

On souhaite modifier la classe RandomNumberGenerator pour la rendre thread-safe sans utiliser ni section critique ni verrou (lock-free donc).

  1. Expliquer comment fonctionne un générateur pseudo-aléatoire et pourquoi l'implantation ci-dessous n'est pas thread-safe.
  2. Utiliser la classe AtomicLong et la méthode compareAndSet pour obtenir une implantation lock-free du générateur pseudo-aléatoire.
  3. Depuis le jdk 1.8, la classe AtomicLong possède une méthode updateAndGet, comment peut-on l'utiliser ici ? Modifiez votre code en conséquence.
  4. Un des inconvénients des champs "atomiques" est qu'ils alourdissent l'allocation nécessaire pour chaque objet. En effet, pour utiliser un long pour chaque objet générateur, il faut allouer un AtomicLong qui permettra lui-même d'accéder de manière atomique à la valeur d'un long, chaque accès nécessitant lui-même une indirection...
    Faites une nouvelle implantation du générateur pseudo-aléatoire qui utilise la classe VarHandle. Un VarHandle ne nécessite qu'une seule instance (static) pour mettre à jour de manière atomique le champ volatile long de n'importe lequel des objets générateur de cette classe.

Exercice 3 - Rendez vous (vous êtes cernés)

On souhaite écrire un petit programme qui permet de simuler le passage de paramètre entre une thread qui fait un calcul et la thread principale (celle qui exécute le main).

  1. Que se passe-t-il lorsqu'on exécute ce code ?
  2. Commenter l'instruction Thread.sleep(1) dans la méthode get puis ré-exécuter le code.
    Que se passe-t-il ?
    Expliquer où est le bug ?
  3. Écrire une classe RendezVous qui fonctionne comme la classe StupidRendezVous mais fonctionne correctement lorsque l'on commente l'instruction Thread.sleep(1).
  4. Regarder l'utilisation du CPU par votre programme avec la commande top. Rappeler ce qu'est une attente active, et expliquer pourquoi la classe RendezVous en est victime.
  5. Corriger le code de la classe RendezVous en utilisant les méthodes wait et notify pour éviter l'attente active. Regardez à nouveau l'utilisation du CPU par votre programme avec la commande top.
  6. Vérifiez que vous gérez les spurious wakeup correctement.