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

Java Discussion :

[Thread][SYNCHRONIZED] problème de synchornisation


Sujet :

Java

  1. #1
    Membre du Club
    Inscrit en
    Avril 2004
    Messages
    101
    Détails du profil
    Informations forums :
    Inscription : Avril 2004
    Messages : 101
    Points : 58
    Points
    58
    Par défaut [Thread][SYNCHRONIZED] problème de synchornisation
    Bonjour,

    j'ai écrit un objet Referenceur qui contient une liste d'objet, voici un résumé :

    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
     
    public class Referenceur {
       private List listeObjet;
     
       Referenceur() {
          listeObjet = new ArrayList();
       }
     
       public void addObject (Object o) {
          listeObjet.add(o);
       }
     
       public void removeObject (Object o) {
          listeObjet.remove(o);
       }
     
       public void removeOldObject () {
          Iterator it = listeObject.iterator();
          while (it.hasNext()) {
             Object o = it.next();
             ...
          }
       }
    }
    voici mon problème : si un ajout ou un retrait est effectué pendant que l'iterator parcours la liste il y a une exception du type :
    java.util.ConcurrentModificationException
    at java.util.AbstractList$Itr.checkForComodification(Unknown Source)
    at java.util.AbstractList$Itr.next(Unknown Source)
    J'ai alors ajouté "synchronized" à la définition des méthodes addObject, removeObject et removeOldObject mais l'exception remonte toujours.


    besoin d'aide...

  2. #2
    duj
    duj est déconnecté
    Membre confirmé

    Profil pro
    Inscrit en
    Juillet 2003
    Messages
    141
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Juillet 2003
    Messages : 141
    Points : 474
    Points
    474
    Par défaut
    salut,

    si , quand tu parcours ta liste avec l'iteraeur, tu la modifie, c'est normal que tu aies ce type d'erreur, c'est insoluble.

    par exemple, ceci ne va pas:


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    List l =...
    Itrator iter = l.iterator();
    while(iter.hasNext()) {
     Object o = iter.next();
     if(.....) l.remove(o);
     
    }
    tu aura l'exception que tu as eu

    tu dois plutôt faire ceci:


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    List l =...
    Itrator iter = l.iterator();
    while(iter.hasNext()) {
     Object o = iter.next();
     if (...) iter.remove();
    }
    Parfois, Google fait des miracles

  3. #3
    Membre du Club
    Inscrit en
    Avril 2004
    Messages
    101
    Détails du profil
    Informations forums :
    Inscription : Avril 2004
    Messages : 101
    Points : 58
    Points
    58
    Par défaut
    bien vu mais c'est pas ça, j'aurais du détailler un peu ma fonction removeOldObject :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    1   public void removeOldObject () { 
    2      Iterator it = listeObject.iterator(); 
    3      while (it.hasNext()) { 
    4         monObject o = (monObject) it.next(); 
    5         if (o.misAjour = false) o.setPerime(true);
    6      }
    7   }

    en fait cette méthode ne modifie pas la liste d'objet.
    Encore une précision : l'erreur remonte sur l'instruction "it.next" de la ligne 4

  4. #4
    Membre régulier
    Profil pro
    Inscrit en
    Août 2003
    Messages
    73
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2003
    Messages : 73
    Points : 78
    Points
    78
    Par défaut
    Bonjour,

    synchronized n'effectue un blocage qu'au niveau de la methode.
    C'est a dire que 2 Thread ne pourront pas utiliser la methode
    simultanement. Mais rien n'empeche 2 methodes synchronized
    d'etre appelees simultanement par 2 Thread differents.
    Donc il faut implementer un blocage dans la classe qui regle ca..

    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
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
     
    	public static class Referenceur {
    		private List listeObjet;
    		private boolean bloque = false; // Verrou
     
    		Referenceur() {
    			listeObjet = new ArrayList();
    		}
     
    		/**
                     * Modifie le blocage
                     */
    		private synchronized boolean setBloque(boolean bloque) {
    			if (bloque) { // Si on veur bloquer
    				if (!this.bloque) { // Si pas deja bloque
    					this.bloque = true; // Bloque
    					return false; // Retourne que ce n'etait pas bloque
    				}
    			} else {
    				this.bloque = false; // Debloque
    			}
    			return bloque; // Retourne que c'etait bloque
    		}
     
    		/**
                     * Applique le blocage
                     */
    		private void bloque() {
    			try {
    				while (setBloque(true)) {
    					Thread.sleep(1000);
    				}
    			} catch (InterruptedException e) {
    			}
    		}
     
    		/**
                     * Supprime le blocage
                     */
    		private void debloque() {
    			setBloque(false);
    		}
     
    		public void addObject(Object o) {
    			bloque();		// Bloque
    			listeObjet.add(o);
    			debloque();		// DeBloque
    		}
     
    		public void removeObject(Object o) {
    			bloque();		// Bloque
    			listeObjet.remove(o);
    			debloque();		// DeBloque
    		}
     
    		public void removeOldObject() {
    			bloque();		// Bloque
    			Iterator it = listeObjet.iterator();
    			while (it.hasNext()) {
    				JPanel o = (JPanel) it.next();
    				if (!o.isBackgroundSet())
    					o.setBackground(Color.GREEN);
    			}
    			debloque();		// DeBloque
    		}
    	}
    Mais, c'est deja bien que tu es pu identifier le probleme.
    Perso, lorsque j'ai rencontre ce probleme, j'ai mis beaucoup de temps a trouver...

    Cordialement,

    PS : N'oublie pas le tag[resolu], quand ton probleme est resolu.
    PS : N'oublie pas le tag [Résolu] (en cliquant sur http://pouiller.eclipse.free.fr/avatar/resolu.gif), si ton problème est résolu...

  5. #5
    duj
    duj est déconnecté
    Membre confirmé

    Profil pro
    Inscrit en
    Juillet 2003
    Messages
    141
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Juillet 2003
    Messages : 141
    Points : 474
    Points
    474
    Par défaut
    synchronized n'effectue un blocage qu'au niveau de la methode.
    C'est a dire que 2 Thread ne pourront pas utiliser la methode
    simultanement. Mais rien n'empeche 2 methodes synchronized
    d'etre appelees simultanement par 2 Thread differents.
    Je ne suis pas du tout sûr de ca. Je pense que quand on appel une méthode synchronize, c'est toute l'instance qui est bloquée (c'est à dire les autres méthodes synchrronise aussi).
    Parfois, Google fait des miracles

  6. #6
    Membre confirmé
    Avatar de Glob
    Homme Profil pro
    Architecte de système d'information
    Inscrit en
    Avril 2002
    Messages
    428
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : Suisse

    Informations professionnelles :
    Activité : Architecte de système d'information

    Informations forums :
    Inscription : Avril 2002
    Messages : 428
    Points : 630
    Points
    630
    Par défaut
    Bonjour.

    "synchronized" ne bloque pas une instance ou une classe, mais un thread.

    Normalement, 2 thread ne peuvent exécuter simultanément 2 méthodes (ou 2 fois la même méthode) synchronisées d'une même instance.

    Bon.

    La méthode de synchro à la main de bidon a l'air pas mal, mais ne fonctionne pas dans tous les cas. Je dirais même que c'est du hasard si ça fonctionne, en raison des mécanismes interne de la jvm qui partagent une même variable entre plusieurs Thread. Il faudrait rajouter le mot clef "volatile" pour la variable "bloque", ce qui devrait régler le problème.

    Sinon, dans le code original du 1er post, j'aurais fait comme ça:
    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
    public class Referenceur { 
       private List listeObjet; 
     
       Referenceur() { 
          listeObjet = new ArrayList(); 
       } 
     
       public void addObject (Object o) { 
          synchronized (listeObjet) {
            listeObjet.add(o);
          }
       } 
     
       public void removeObject (Object o) { 
          synchronized (listeObjet) {
            listeObjet.remove(o); 
          }
       } 
     
       public void removeOldObject () { 
          synchronized (listeObjet) {
            Iterator it = listeObject.iterator(); 
            while (it.hasNext()) { 
               Object o = it.next(); 
               ... 
            } 
          }
       } 
    }
    Glob
    What would you do if you were not afraid?

    Cours et tutoriels pour apprendre Java , FAQ Java, et Forum Java

  7. #7
    Membre régulier
    Profil pro
    Inscrit en
    Août 2003
    Messages
    73
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2003
    Messages : 73
    Points : 78
    Points
    78
    Par défaut
    Respect : je viens de comprendre les limites de la solution que j'ai propose...

    Et du meme coup de comprendre a quoi sert le mot cle volatile que je n'ai jamais utilise...

    Cordialement,
    PS : N'oublie pas le tag [Résolu] (en cliquant sur http://pouiller.eclipse.free.fr/avatar/resolu.gif), si ton problème est résolu...

  8. #8
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Décembre 2002
    Messages
    32
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Décembre 2002
    Messages : 32
    Points : 32
    Points
    32
    Par défaut
    Je ne suis pas tout à fait d'accord avec bidon
    Mais rien n'empeche 2 methodes synchronized
    d'etre appelees simultanement par 2 Thread differents.
    ... si elles sont synchronisées sur this, elles ne seront pas appelées simultanément.

    En outre, je n'ai jamais vu nulle part qu'on devait "implémenter" soi-même l'équivalent d'un synchronized; mais ça existe peut-être... ; cela dit, sur un exemple simple, je serais vraiment étonné qu'il faille le faire !

    Philippe

  9. #9
    Membre du Club
    Inscrit en
    Avril 2004
    Messages
    101
    Détails du profil
    Informations forums :
    Inscription : Avril 2004
    Messages : 101
    Points : 58
    Points
    58
    Par défaut
    désolé, je me suis absenté quelques jours...

    merci pour toutes ces réponses, je vais faire différents tests et je vous donnerai les résultats.

  10. #10
    Membre du Club
    Inscrit en
    Avril 2004
    Messages
    101
    Détails du profil
    Informations forums :
    Inscription : Avril 2004
    Messages : 101
    Points : 58
    Points
    58
    Par défaut
    finallement j'ai modifié mon code en supprimant directement l'objet de la liste et en faisant un remove sur l'iterator, ça résout le problème et c'est le plus simple je crois.

    par contre je pense que bidon n'avait pas tort concernant sa remarque :
    Mais rien n'empeche 2 methodes synchronized
    d'etre appelees simultanement par 2 Thread differents.
    en rapport avec le design pattern Singleton je crois.

    Merci pour votre aide.

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

Discussions similaires

  1. [VB Net] Thread synchrone ?
    Par pinson dans le forum VB.NET
    Réponses: 3
    Dernier message: 20/04/2007, 08h58
  2. [Thread]Synchronized
    Par soad dans le forum Concurrence et multi-thread
    Réponses: 15
    Dernier message: 10/10/2005, 20h16
  3. [Thread][synchronized] Pb d'executions simultanees d'une methode
    Par Higestromm dans le forum Concurrence et multi-thread
    Réponses: 5
    Dernier message: 02/09/2005, 12h04
  4. [thread] synchronize ou pas ?
    Par dvarrel dans le forum Langage
    Réponses: 4
    Dernier message: 26/07/2004, 19h09
  5. [Thread] Synchronize
    Par Pedro dans le forum Langage
    Réponses: 9
    Dernier message: 06/07/2004, 13h30

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