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

Concurrence et multi-thread Java Discussion :

Thread - Accès concurrent à une List


Sujet :

Concurrence et multi-thread Java

  1. #1
    Membre habitué
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2009
    Messages
    391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2009
    Messages : 391
    Points : 185
    Points
    185
    Par défaut Thread - Accès concurrent à une List
    Bonjour à tous ,

    j'essaie de programmer un petit "zelda-like" en Java avec Libgdx, et comme il y aura pas mal d'autres éléments que mon personnage sur la map; je commence à utiliser les Threads pour les gérer. Cependant, mon programme plante sur une exception que je n'arrive pas à gérer et d'après ce que j'ai pû en trouver sur internet, c'est un problème d'accès concurrent (mais rien de sûr).

    L'exception est la suivante :

    Exception in thread "Tort 1" Exception in thread "Tort 2" com.badlogic.gdx.utils.GdxRuntimeException: #iterator() cannot be used nested.
    at com.badlogic.gdx.utils.Array$ArrayIterator.hasNext(Array.java:523)
    at com.defel.game.entite.ennemi.Ennemi.deplacementAleatoire(Ennemi.java:368)
    at com.defel.game.entite.ennemi.Ennemi.run(Ennemi.java:234)

    Le code concerné semble être le suivant (d'ailleurs, quand je le supprime, je n'ai plus l'erreur mais j'en ai besoin lol) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    for (MapObject obj : InfosSingleton.getInstance().getCollisionObjects()) {
    	RectangleMapObject rectMapObject = (RectangleMapObject) obj;
    	Rectangle rectObject = rectMapObject.getRectangle();
     
    	if(Intersector.overlaps(rectObject, rectangleColl)){
    		bloquer = true;
    	}
    }
    Ce code sert à parcourir une List de MapObject qui est contenue dans un Singleton. Je pense que le problème vient du parcours de cette liste. Pour info, la méthode est déclarée "private synchronized".

    Ca commence à faire un moment que je suis sur cette question =D j'espère qu'un expert charitable passera par là pour me donner son avis.

    Merci d'avance

  2. #2
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    Le synchronized, dans ton cas, ne sert à rien là où tu l'a mis. Il protège des méthodes de Ennemi, mais je suppose que tu as plusieurs Ennemi et que tous accèdent à InfosSingleton.getInstance().getCollisionObjects().

    C'est ta liste qu'il faut protéger. Les bouts de code utilisant ta liste doivent être protégés comme ceci:


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    synchronized(InfosSingleton.getInstance().getCollisionObjects()){
      for (MapObject obj : InfosSingleton.getInstance().getCollisionObjects()) {
    	RectangleMapObject rectMapObject = (RectangleMapObject) obj;
    	Rectangle rectObject = rectMapObject.getRectangle();
     
    	if(Intersector.overlaps(rectObject, rectangleColl)){
    		bloquer = true;
    	}
      }
    }
    Mais si tu as beaucoup de liste différentes, ça va vite être galère à gérer et les deadlocks vont commencer à faire leur apparition. Tu peux prendre un verrou plus global, qui n'est pas spécifique à la liste:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    synchronized(InfosSingleton.getInstance()){
      for (MapObject obj : InfosSingleton.getInstance().getCollisionObjects()) {
    	RectangleMapObject rectMapObject = (RectangleMapObject) obj;
    	Rectangle rectObject = rectMapObject.getRectangle();
     
    	if(Intersector.overlaps(rectObject, rectangleColl)){
    		bloquer = true;
    	}
      }
    }

  3. #3
    Membre habitué
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2009
    Messages
    391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2009
    Messages : 391
    Points : 185
    Points
    185
    Par défaut
    Bonjour ,

    merci d'avoir répondu aussi rapidement et merci, grâce à toi j'ai compris à quoi servait le synchronized.

    Par contre, ça ne fonctionne pas mieux avec ça.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    synchronized (InfosSingleton.getInstance()) {
    	for (MapObject obj : InfosSingleton.getInstance().getCollisionObjects()) {
    		RectangleMapObject rectMapObject = (RectangleMapObject) obj;
    		Rectangle rectObject = rectMapObject.getRectangle();
     
    		if(Intersector.overlaps(rectObject, rectangleColl)){
    			bloquer = true;
    		}
    	}
    }
    Sur un autre site, on m'a conseillé de faire le code suivant et ça fonctionne mieux :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    MapObjects test = InfosSingleton.getInstance().getCollisionObjects();
     
    for(int i = 0 ; i < test.getCount() ; i++){
     
    	RectangleMapObject rectMapObject = (RectangleMapObject) test.get(i);
    	Rectangle rectObject = rectMapObject.getRectangle();
     
    	if(Intersector.overlaps(rectObject, rectangleColl)){
    		bloquer = true;
    	}
    }
    Cependant, je ne vois pas pourquoi ça fonctionne avec ça et pas avec le code que tu m'a dis d'essayer :/
    Au passage, je m'étais trompé, c'était une Collection et pas une List, mais je pense que ça ne change rien au problème.
    Si tu as une explication, je suis preneur ^^.

    Merci encore.

  4. #4
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    Citation Envoyé par paladice Voir le message
    Par contre, ça ne fonctionne pas mieux avec ça.
    Tu l'a bien fait partout où tu itère sur tes listes? Le message d'erreur se plaint de plusieurs parcours simultanés, il faut donc protéger tout ces parcours.

    Citation Envoyé par paladice Voir le message
    Sur un autre site, on m'a conseillé de faire le code suivant et ça fonctionne mieux :
    Ca ne fait que cacher le problème sous le tapis. Tu utilise un index pour éviter de passer par l'itérateur qui permettrait de détecter ton problème de concurrence. Le problème de base c'est que tu manipule la même collection dans plusieurs threads en même temps, ce n'est pas supporté.

  5. #5
    Membre habitué
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2009
    Messages
    391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2009
    Messages : 391
    Points : 185
    Points
    185
    Par défaut
    =D Effectivement, ça fonctionne !
    Puisque j'avais le même message d'erreur, j'avais pas vu que ça concernait un autre bout de code ^^.
    Merci beaucoup.

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

Discussions similaires

  1. [threads] Problème d'accès concurrent à une liste
    Par Traroth2 dans le forum Général Java
    Réponses: 5
    Dernier message: 26/11/2009, 17h43
  2. [Oracle] Accès concurrent à une base de données
    Par schniouf dans le forum JDBC
    Réponses: 8
    Dernier message: 29/09/2006, 16h10
  3. javascript : accès a une liste déroulante.
    Par pierreonxbox dans le forum Général JavaScript
    Réponses: 1
    Dernier message: 31/03/2006, 11h20
  4. Réponses: 9
    Dernier message: 15/02/2006, 20h54
  5. accés concurrent à une table
    Par shout dans le forum Oracle
    Réponses: 5
    Dernier message: 06/10/2005, 10h54

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