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

Langage Java Discussion :

[synchronized] ConcurrentModificationException sur une itération


Sujet :

Langage 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 [synchronized] ConcurrentModificationException sur une itération
    Bonjour,

    j'ai écrit un bout de code qui démarre deux threads, l'un ajoute des données à une liste et l'autre en retire.
    L'utilisation d'un Iterator pour retrouver l'objet à supprimer provoquent rapidement une ConcurrentModificationException.

    Avez-vous une solution à me proposer.

    ex :
    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
     
    public class Tmp {
     
    	private List datas = new Vector();
     
    	public static void main(String[] args) {
    		Tmp t = new Tmp();
    		t.new ThreadAdd().start();
    		t.new ThreadRemove().start();
    	}
     
    	private class ThreadAdd extends Thread {
    		public void run() {
    			while (true) {
    				System.out.println(datas);
    				datas.add(new Object());
     
    				attendre(20);
    			}
    		}
    	}
     
    	private class ThreadRemove extends Thread {
    		public void run() {
    			while (true) {
    				attendre(30);
     
    				System.err.println(datas);
    				//synchronized (datas) { => inefficace 
    					Iterator it = datas.iterator();
    					while (it.hasNext()) {
    						Object o = it.next();
    						datas.remove(0);
    					}
    				//}
    			}
    		}
    	}
     
    	private static void attendre(long l) {
    		try {
    			Thread.sleep(l);
    		} catch (InterruptedException e) {
    			e.printStackTrace();
    		}
    	}
    }
    et en quelques millièmes de seconde j'obtiens :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    java.util.ConcurrentModificationException
    	at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:448)
    	at java.util.AbstractList$Itr.next(AbstractList.java:419)
    	at test.Tmp$ThreadRemove.run(Tmp.java:41)

  2. #2
    Membre chevronné
    Profil pro
    Fabrication GED
    Inscrit en
    Octobre 2005
    Messages
    1 405
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France, Seine Maritime (Haute Normandie)

    Informations professionnelles :
    Activité : Fabrication GED

    Informations forums :
    Inscription : Octobre 2005
    Messages : 1 405
    Points : 1 958
    Points
    1 958
    Par défaut
    List list = Collections.synchronizedList(new ArrayList(...));
    ( extrait de la javadoc )
    il ne faut plus utiliser de Vector.
    Sinon tu peux toujours synchroniser ton iterator :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    synchrnonized(this.datas){
       Iterator ...
    }

  3. #3
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Salut,


    En réalité le synchronized sur ta collection n'est pas inefficace, mais il y a deux problèmes dans ton code qui peuvent provoquer des ConcurrentModificationException.


    Cette exception survient pendant le parcours d'une collection via un itérateur alors que la collection est modifié entre temps, que ce soit par un autre thread ou par le même thread...

    1. Tu dois donc utiliser une synchronisation pour éviter que le thread d'ajout ne modifie la collection pendant le parcours. Cela bien entendu car Vector est thread-safe. Si tu aurais utilisé une autre type de collection non thread-safe il faudrait utiliser les méthodes Collections.synchronizedXXX() (note au passage que c'est souvent recommandé d'utiliser cela plutôt que Vector).
    2. Mais si tu as quand même une exception, c'est que tu peux avoir une ConcurrentModificationException au sein du même thread : lors du parcourt d'une collection via un itérateur, on ne doit pas modifier la collection pendant ce parcours, à moins d'utiliser les méthodes de l'itérateur en question. Il faut donc que tu utilises la méthode remove() de l'itérateur et non pas de ta liste...



    Au final, ton itération doit ressembler à cela :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    			synchronized (datas) {
    				Iterator it = datas.iterator();
    				while (it.hasNext()) {
    					Object o = it.next();
    					it.remove();
    				}
    			}

    Enfin quelques remarques en passant :
    • Comme je l'ai dit, Vector n'est plus vraiment d'actualité. Tu pourrais surement utilisé d'autre classe peut-être plus adapté. Et c'est d'autant plus vrai sous Java 5.0 et son API de concurrence qui propose un bon paquet de collection thread-safe et performante...
    • Si tu veux simplement supprimé tous les éléments tu peux directement utilisé la méthode clear() (je dis ca au cas où, même si je pense que par la suite ton itération effectuera des traitements sur les objets supprimé)


    a++

  4. #4
    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
    Merci pour ces réponses rapides, ça semble fonctionner.

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

Discussions similaires

  1. Erreur de compilation sur une itération
    Par JeanNoel53 dans le forum Débuter avec Java
    Réponses: 15
    Dernier message: 04/05/2015, 22h29
  2. Itération sur une Map
    Par singleProject dans le forum Collection et Stream
    Réponses: 3
    Dernier message: 16/10/2008, 11h54
  3. Itération sur une liste en JSF?
    Par toutoune60 dans le forum JSF
    Réponses: 2
    Dernier message: 26/12/2007, 09h43
  4. Réponses: 3
    Dernier message: 06/11/2007, 11h18
  5. blocage sur une méthode synchronized
    Par rockelite dans le forum Général Java
    Réponses: 3
    Dernier message: 03/05/2006, 22h28

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