:: Enseignements :: ESIPE :: E4INFO :: 2017-2018 :: Concurrence ::
[LOGO]

Examen de Concurrence


L'examen est composé de deux exercices indépendants qui peuvent être traités dans l'ordre que vous voulez.
Rappel: vous devez configurer le workspace d'Eclipse (File > Switch WorkSpace) pour qu'il corresponde au répertoire EXAM présent dans le home de votre session de TP noté.
Attention à bien lire le sujet en entier.

Exercice 1 - Statistiques paresseuses

On souhaite calculer des statistiques sur un tableaux d'entiers de façon paresseuse, c'est à dire, calculer les statistiques sur le tableau au moment (et pas avant) où un utilisateur demande les statistiques avec la méthode getStat pour la première fois. Et si l'on appelle getStat une autre fois, les statistiques ne devraient pas être recalculées.
En fait, ici, ce que l'on veut, c'est une contrainte plus forte: une fois qu'un objet java.util.IntSummaryStatistics a été renvoyé par la méthode getStat, tous les appels suivant à la méthode getStat doivent renvoyer exactement le même objet java.util.IntSummaryStatistics (au sens de ==).
Note: pour votre culture, le langage Scala a un mot clé nommé lazy qui provoque exactement ce comportement. C'est ce que l'on souhaite le simuler en Java.
Comme c'est un examen de concurrence et pas de Java, on vous fournit le code qui calcule les statistiques, mais qui n'est pas thread safe:
LazyStat.java.
Les tests JUnit pour toutes les questions de l'exercice sont dans la classe LazyStatTest.java.
Attention, les tests sont volontairement simples pour que vous puissiez les lire (mais ne couvrent pas forcément toutes les erreurs possibles). Ils peuvent reporter des erreurs sur la console au lieu de reporter les erreurs dans la partie graphique. Donc un test passe s'il est vert et qu'il ne fait pas d'erreur sur la console.

  1. Modifier le code de la classe LazyStat pour répondre au problème en utilisant les ReentrantLock.
  2. Copier/coller le code de votre classe LazyStat dans une classe OldLazyStat pour faire une sauvegarde. Puis modifier le code de la classe LazyStat pour fournir une implantation lock-free utilisant la méthode compareAndSet de l'API des VarHandle

Exercice 2 - Le Juste Prix

"Le Juste Prix", The price is right en anglais, est un jeu télévisé ou plusieurs candidats s'affrontent pour gagner un article (dont le prix n'est pas connu par les candidats). Chaque candidat propose un prix et le candidat qui indique le prix le plus proche du prix réel d'un article gagne cet article.
Dans cet exercice, vous devez implanter la même mécanique de jeu avec une thread simulant un candidat.
Les tests JUnit pour toutes les questions de l'exercice sont dans la classe ThePriceIsRightTest.java.
Attention, les tests sont volontairement simples pour que vous puissiez les lires. Ils peuvent reporter des erreurs sur la console au lieu de reporter les erreurs dans la partie graphique. Donc un test passe s'il est vert et qu'il ne fait pas d'erreur sur la console.
  • Le constructeur de la classe ThePriceIsRight est initialisé avec le prix réel de l'article, ainsi que le nombre de candidats.
    Par exemple, si un article vaux 100 et qu'il y a deux threads, on initialise ainsi:
           ThePriceIsRight tpir = new ThePriceIsRight(100, 2);
          

    Le nombre de participants doit être un nombre positif supérieur strict à zéro.
  • La méthode propose prend en paramètre un entier qui correspond au prix proposé par un candidat (une thread). Cette méthode bloque tant que tous les candidats n'ont pas soumis leur prix puis elle renvoie true à la thread qui a proposé le prix le plus proche et false à toutes les autres threads.
  • Si plus de threads que le nombre de participants indiqué à la construction exécutent la méthode propose, la proposition de prix des threads supplémentaires ne sera pas prise en compte et la méthode propose renvoie false.
  • Si deux participants proposent le même prix et que c'est le prix le plus proche du prix réel, alors le premier participant (la première thread ayant proposé le prix) est le gagnant.
  • Si une thread qui a déjà proposé un prix est interrompue, son prix est retiré des prix pris en compte (comme si elle n'avait pas joué), donc la méthode propose renvoie false.
    De plus, le juste prix est alors immédiatement calculé sur les threads restants (les threads sont donc débloquées même sans avoir atteint le nombre de participants requis).
  • Dans le cas où il y avait un seul participant et qu'il est interrompu, aucune thread n'a le juste prix et la méthode propose doit renvoyer false pour tout le monde.

Quelques indications:
  • Comme il faut pouvoir retirer la proposition de la thread interrompue, il va falloir se souvenir de quelle thread a voté quoi.
  • Posez-vous la question de qui doit faire le calcul (et à quel moment) pour savoir quelle est la thread gagnante, c'est à dire, celle qui est la plus proche du prix réel de l'article.
  • Être le plus proche du juste prix veut dire avoir la plus petite distance par rapport au prix réel, donc avoir la valeur la plus petite avec la fonction suivante:
            private int distance(int price) {
              return Math.abs(price - realPrice);
            }
           
  • Pour le code qui trouve la thread gagnante, si vous aimez jouer avec les Stream, vous pouvez utiliser le collector Collectors.minBy, mais vous pouvez aussi écrire le code à la main, pourvu que ce soit correct.