IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Développement Web en Java Discussion :

Dans quel cas utilise-t-on Synchronized ?


Sujet :

Développement Web en Java

  1. #1
    Membre averti
    Homme Profil pro
    Développeur Java
    Inscrit en
    Novembre 2022
    Messages
    51
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : Novembre 2022
    Messages : 51
    Par défaut Dans quel cas utilise-t-on Synchronized ?
    Bonjour,

    Je me suis lancé dans l'analyse de performance en comparant l'utilisation d'un seul processeur versus plusieurs (qu'on appelle cœurs sur certaines machines).

    Pour l'instant avec un programme test, en éclatant la lecture d'une table MySQL de 7000 lignes, je passe de 94 secondes à 16 secondes avec 4 processeurs en découpant les recherches par gammes de numéros (par exemple de 0 à 999 puis de 1000 à 1999, etc..)
    Ceci m'encourage revoir ou à soigner le design de mes applications futures lorsqu'il y aura des traitements séquentiels longs pour chaque ligne.
    Toutefois pour être sûr que dans certains cas je ne risque pas d'inter-locks il faut que je comprenne parfaitement comment sont protégés les programmes et les variables.

    1. Supposons qu'une Classe maître démarre 3 fois la même sous-classe définie comme runnable. Est-ce que les variables (non static) sont uniques à chaque instance de cette classe ?

    2. Supposons que l'on n'ait qu'une seule instance d'une classe avec plusieurs threads lancés chacune ayant sa méthode run, mais partageant une autre méthode. par exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
     
    Thread th1 =new Thread("T1") {
        public void run({
           int rc = maMéthode(argument1);  
      }
    }.start();
     
    Thread th2 =new Thread("T2") {
        public void run() 
      {
           int rc = maMéthode(argument2);  
      }
    }.start();
     
    public static int maMéthode(int arg)
    {
       int x = arg;
       .....
      return rc;
    }
    Dans ce cas, dois-je utiliser synchronized pour protéger la variable x ? Que ce soit une méthode définie comme static ou non ?

    Cela peut sembler trivial comme question, mais je ne suis pas sûr de moi.

    Merci d'avance

    Gérard

  2. #2
    Membre très actif

    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    486
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2009
    Messages : 486
    Billets dans le blog
    5
    Par défaut
    Pour commencer, il ne faut jamais utiliser un thread.

    Il faut différentier la tâche, en l’occurrence le Runnable, du la façon de lancer la tâche.

    Pour cela, il faut plutôt utiliser le framework exécutor ( https://www.jmdoudoux.fr/java/dej/chap-executor.htm ).

    Pour répondre à la question, il faut utiliser sychronized à chaque fois qu'une donnée ou qu'une méthode est utilisée par plusieurs Thread et que l'on veut que ce soit cohérent.

    Pour une donnée, le problème est que le thread 1 la modifie, et que pendant ce temps, le thread 2 la lit. Là, non, le thread 2 doit d'abord attendre que le thread 1 ait finit de la modifier.

    De même, si 2 thread utilisent une méthode de modification, il serait mal venu, aussi pour des questions de cohérence, que la modification se fasse en même temps.

    Notez que pour les données, on a l'AtomicBoolean, AtomicNumber...

    Pour les méthodes, on peut, si on implémente une interface, l'implémenter dans un milieu non thred-safe, et utiliser le Design Pattern Decorateur ( https://fr.wikipedia.org/wiki/D%C3%A...de_conception) ) pour rendre le tout thread-safe.

    Exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    public MonInterface{
     
      void maMethode();
     
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    public MaClasse() implements MonInterface{
     
      @Override
      public void maMethode(){
        //Mon implémentation
      }
     
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    public void MonDecorateur implements MonInterface{
     
      private final MonInterface aInterface;
     
      public MonDecorateur(MonInterface aInterface){
        this.aInterface = aInterface;
      }
     
      @Override
      public synchronized void maMethode(){
        aInterface.maMethode();
      }
    }
    C'est ce qui est fait lorsque l'on fait Collections.synchronizedList(new ArrayList<>()) par exemple.

  3. #3
    Membre averti
    Homme Profil pro
    Développeur Java
    Inscrit en
    Novembre 2022
    Messages
    51
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : Novembre 2022
    Messages : 51
    Par défaut
    Tout d'abord, merci pour ta réponse. Je ne connaissais pas le framework executor. Je vais lire aujourd'hui tout ce que cela concerne. En particulier si cela peut m'éviter d'utiliser les threads explicitement.

    Dans la première question de mon précédent post, je parlais de définir une classe comme runnable qui serait instanciée par une autre classe (classe maitre). De la façon ci-dessous.
    Ma question était "est-ce qu'il y a des risques de blocage" ou de partage des variables par les différentes classes instanciées". ? Autrement dit est-ce que toutes les variables sont privées pour chaque occurrence ? La variable x dans mon exemple ? (sauf, bien sûr les variables définies comme static).

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
     
    package exercices;
     
    public class MonTraitement implements Runnable 
    {
     
        public MonTraitement( )    {    }
     
        @Override
        public void run()
       {
    		int x = 0;
                    ........
       }
    }
     
     
    public class TestRunnable 
    {
    	 public static void main(String[] args) 
    	 {   
    		 Runnable runnable = new MonTraitement();
    		    for (int i = 0; i < 5; i++) 
    		    {
    		      Thread thread = new Thread(runnable);  // on instancie 5 fois la même classe dans des threads différents. 
    		      System.out.println(thread.getId());
    		      thread.start();
    		    }
    	}
    }
    Merci encore pour ton aide.

    Gérard

  4. #4
    Membre averti
    Homme Profil pro
    Développeur Java
    Inscrit en
    Novembre 2022
    Messages
    51
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : Novembre 2022
    Messages : 51
    Par défaut
    En fait je viens de répondre moi-même à ma question, en modifiant légèrement la classe instanciée. Je m'aperçois que les variables n'ont pas les mêmes valeurs après exécution alors que ce devrait être identique. Que ce soit si elles sont statiques ou non.

    Merci encore
    Gégé

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
     
    package exercices;
     
    public class MonTraitement implements Runnable 
    {
    	public static int x =0;
        private int y = 0;
        public MonTraitement() {}
     
    	@Override
    	public synchronized void run()
    	{
    		 for (int i= 0; i<3; i++)
    		 {
    			 x++;
    			 y++;
    		 }
    		 System.out.println(Thread.currentThread().getName() +  " ---> x=" + x  + " ; y="+ y);
     
    	}
    }

  5. #5
    Membre très actif

    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    486
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2009
    Messages : 486
    Billets dans le blog
    5
    Par défaut
    Le problème est que tu as une classe qui est attaquée par plusieurs Thread.

    Or, au sein de ta classe, la donnée doit restée cohérente.

    Lorsqu'elle est modifiée, on ne doit pas pouvoir lire d'un autre Thread la donnée.

    De fait, on le fait en plaçant judicieusement les mots clés synchronized.

    Ou mieux, on peut utiliser les truc Atomic (AtomicBoolean, AtomicInteger), Les Décorateurs (Collections.synchronizedMap(),...), ou les objets safe-thread (ConcurrentHashMap...).

  6. #6
    Membre très actif

    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    486
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2009
    Messages : 486
    Billets dans le blog
    5
    Par défaut
    Une autre chose qui peut être bien est de différentier la donnée du traitement. Tu injecte (Injection de dépendance) la donnée dans le traitement.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 55
    Dernier message: 18/03/2014, 12h11
  2. Réponses: 17
    Dernier message: 05/03/2014, 14h03
  3. Dans quel cas utiliser PHP, .Net ou Java ?
    Par mic79 dans le forum Langage
    Réponses: 4
    Dernier message: 28/11/2008, 18h58
  4. Quand et dans quels cas utiliser les méthodes repaint() et validate()?
    Par kayzra dans le forum Interfaces Graphiques en Java
    Réponses: 14
    Dernier message: 02/08/2007, 15h46
  5. [Zope] Dans quel cas utiliser zope ?
    Par kalimero dans le forum Zope
    Réponses: 3
    Dernier message: 26/07/2005, 09h08

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo