Valeur du getter impossible à tester

-
Bonsoir à tous,

J'ai un petit problème dans le code suivant :
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.Timer;

public class Ex {
  int attribut ;
  Timer chrono;
  private ActionListener refreshChrono ;
  
  public Ex(){
   attribut = 0;
   chrono = new Timer(1000,refreshChrono);
   refreshChrono = new ActionListener() {
   public void actionPerformed(ActionEvent e1)
    { 
      attribut = 1;
    }
    };
     
     chrono = new Timer(1000,refreshChrono);
     chrono.start();
     
    }
  
  public static void main(String[] args){
   
   Ex exmple = new Ex();
   System.out.println(exmple.get());
   
   while(true){
     System.out.println(exmple.get());
     
     if(exmple.get() == 1) {
      System.out.println("CoucouMain");
     }
    }
 }

  int get() {
   return attribut;
  }
}


En effet quand dans le while du main, je print exmple.get() je rentre dans le if alors que si je commente le print je n'y rentre plus..
Si quelqu'un sait m"expliquer pourquoi je suis preneur !
Merci d'avance :)
Afficher la suite 

Votre réponse

1 réponse

Meilleure réponse
Messages postés
15937
Date d'inscription
samedi 31 mai 2008
Statut
Modérateur
Dernière intervention
14 février 2019
96
1
Merci
Bonjour,

C'est une question très intéressante, il m'a fallu quelques minutes avant de trouver la solution, c'est le genre de piège où je pourrais encore me faire avoir.

Déjà on peut simplifier ton code et j'en profite pour te montrer une alternative afin d'éviter d'utiliser du code Swing alors que tu n'as pas d'interface graphique (mais le bug reste le même).

import java.util.concurrent.*;
// import javax.swing.Timer;

public class Ex {
    private int attribut;

    public Ex() {
        // new Timer(1000, e -> attribut = 1).start();
        Executors.newSingleThreadScheduledExecutor().scheduleAtFixedRate(() -> attribut = 1, 1L, 1L, TimeUnit.SECONDS);
    }

    public static void main(String[] args) {
        Ex ex = new Ex();
        while (true) {
            // System.out.println(ex.attribut);
            if (ex.attribut == 1) {
                System.out.println("CoucouMain");
            }
        }
    }
}

Pour corriger le bug, il faut rajouter le mot clé volatile à ton attribut :
private volatile int attribut;

Tu trouveras beaucoup d'explication sur ce mot clé, par exemple ici, ce qu'il se cache derrière c'est une optimisation de la JVM qui met en cache la valeur de l'attribut, mais il faut la forcer à se mettre à jour.

Dire « Merci » 1

Heureux de vous avoir aidé ! Vous nous appréciez ? Donnez votre avis sur nous ! Evaluez CodeS-SourceS

Codes Sources 117 internautes nous ont dit merci ce mois-ci

FlorianGaudon
Messages postés
1
Date d'inscription
vendredi 25 janvier 2019
Dernière intervention
26 janvier 2019
-
Bonjour ! :)
Merci beaucoup pour la réponse précise et rapide ! J'ai simplifié mon code de base volontairement pour que la recherche du bug soit plus simple mais de base j'utilise une interface graphique.
Mais du coup je doit rajouter volatile à tous mes attributs qui peuvent être accéder par la déclaration d'un objet ?
A chaque fois que je vais vouloir faire ex.attribut il faudra que l'attribut concerné soit déclaré en volatile ?!

Merci encore de ta réponse rapide et efficace ! :D
KX
Messages postés
15937
Date d'inscription
samedi 31 mai 2008
Statut
Modérateur
Dernière intervention
14 février 2019
96 > FlorianGaudon
Messages postés
1
Date d'inscription
vendredi 25 janvier 2019
Dernière intervention
26 janvier 2019
-
C'est un problème qui ne se pose que parce que tu as un thread d'écriture différent des threads de lecture, si ton objet était construit, modifié et lu par le même thread (ce qui est souvent le cas) il n'y aurait pas de conflit.

volatile
va forcer la JVM à relire la valeur de l'objet entier, donc même s'il n'y a qu'un seul attribut volatile, ils seront tous mis à jour. Mais pour la clarté du code, il vaut mieux ajouter le mot clé volatile à chaque attribut qui serait encore concerné si on supprimait tous les autres attributs.

Voir l'article de Brian Goetz (architecte du langage Java) : Java theory and practice : Managing volatility
Commenter la réponse de KX

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.