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 :

Un Thread en tant que classe interne, problème de synchro?


Sujet :

Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Décembre 2009
    Messages
    31
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Décembre 2009
    Messages : 31
    Par défaut Un Thread en tant que classe interne, problème de synchro?
    Bonjour,

    J'ai vu pas mal de code ressemblant à ceci sur internet et il est vrai que j'ai toujours 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
     
    public class Test
    {
       public void method1()
       {
          Thread t = new Thread("exemple"){
             @Override
             public void run()
             {
                ...
                method2();
             }
             };
     
          t.start();
       }
     
       public void method2()
       {
          ...
       }
    }
    Peut-il y avoir des problèmes de concurrences/synchronisation?

    Si la method2() effectue des modifications sur des variables et que le run() du Thread t est plus complexe (il fait pleins de traitements et appelle plusieurs fois method2() le tout dans une boucle par exemple).
    Que va-t-il se passer lorsque l'on utilisera la méthode method2() depuis une instance de Test? Ou si on touche aux variables qui sont modifié dans method2() alors que le Thread t tourne (et fait des modifications constamment)?

    Autres questions:

    D'après la doc java, une instance d'une classe interne ne peux vivre qu'à l'intérieur d'une instance de la classe de base (voir "inner classes" http://docs.oracle.com/javase/tutori...OO/nested.html). Qu'en est-il pour un Thread? Est-ce que le Thread t subsistera si l'instance de Test est détruite?


    Autres exemples:

    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 Test2
    {
       public final  LinkedList<String> queue = new LinkedList<String>()
     
       public void method1()
       {
          Thread t = new Thread("exemple"){
             @Override
             public void run()
             {
                ...
                queue.add("test");
                ...
                queue.pop();
                ...
             }
             };
     
          t.start();
       }
     
       public void method2()
       {
          ...
          queue.clear();
          ...
       }
    }
    Si entre le .add() et le .pop() du Thread, la méthode method2() est appelé, il y aura une erreur sur le .pop(). Comment gérer ça?


    Merci d'avance pour vos réponses :-)

  2. #2
    Expert éminent
    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
    Billets dans le blog
    1
    Par défaut
    Salut,

    Citation Envoyé par gagou7 Voir le message
    Peut-il y avoir des problèmes de concurrences/synchronisation?
    Oui. Le fait que le thread soit une classe interne ou non n'a aucun impact sur les problèmes de concurrences/synchronisation...

    C'est impossible de répondre exactement à cela sans le code exact. Mais en gros il faut éviter le partage d'objet non thread-safe entre différents threads...

    Citation Envoyé par gagou7 Voir le message
    D'après la doc java, une instance d'une classe interne ne peux vivre qu'à l'intérieur d'une instance de la classe de base (voir "inner classes" http://docs.oracle.com/javase/tutori...OO/nested.html). Qu'en est-il pour un Thread? Est-ce que le Thread t subsistera si l'instance de Test est détruite?
    Plus précisément cela signifie que la classe interne est lié à la classe englobante. Cela n'a aucun impact sur sa durée de vie ou son status de thread...


    a++

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Décembre 2009
    Messages
    31
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Décembre 2009
    Messages : 31
    Par défaut
    Merci pour ta réponse.

    Citation Envoyé par adiGuba Voir le message
    Plus précisément cela signifie que la classe interne est lié à la classe englobante. Cela n'a aucun impact sur sa durée de vie ou son status de thread...
    Aucun impact sur sa durée de vie? Si l'instance de Test est détruite, comment le Thread peut-il accéder à la méthode méthod2()?

    J'ai rajouté un exemple plus concret.

    Et une autre question:

    Dans mon tout premier exemple, si une autre méthode (méthode3() disons...) de Test effectue un traitement lourd et long. Le Thread t peut-il appelé la méthode méthode2()? Ou sera-t-il bloqué?

    Merci encore :-)

  4. #4
    Expert éminent
    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
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par gagou7 Voir le message
    Aucun impact sur sa durée de vie? Si l'instance de Test est détruite, comment le Thread peut-il accéder à la méthode méthod2()?
    La classe interne contient une référence vers la classe conteneur. Donc ce cas ne peut pas se produire...

    Citation Envoyé par gagou7 Voir le message
    J'ai rajouté un exemple plus concret.
    Tu manipules un objet qui n'est pas thread-safe depuis différents threads, donc tu encours des problèmes aléatoires.

    Cela n'a rien à voir avec la classe interne mais uniquement avec les threads.
    Si tu partage un objet entre plusieurs threads tu dois soit utiliser un objet thread-safe (et donc qui gère déjà les problème potentielle), soit synchronisé les accès d'une manière ou d'une autre...

    Citation Envoyé par gagou7 Voir le message
    Dans mon tout premier exemple, si une autre méthode (méthode3() disons...) de Test effectue un traitement lourd et long. Le Thread t peut-il appelé la méthode méthode2()? Ou sera-t-il bloqué?
    Si les méthodes n'utilisent pas les mêmes données il n'y aura aucun problème...

    a++

  5. #5
    Membre Expert
    Inscrit en
    Mai 2006
    Messages
    1 364
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 1 364
    Par défaut
    En complément de la réponse d'adiGuba, j'ajouterais une petite explication sur le fonctionnement de la mémoire en Java. Un objet est détruit si et seulement si il n'est plus référencé. Dans le cas dont tu parles, le thread possède une réference sur l'objet donc celui-ci ne sera pas détruit tant que le thread tourne.

    Sinon, pour la gestion des problemes de synchronisation, voir le mot clé "synchronized". C'est un peu long a expliquer en quelques mots mais il y a plein de tutos bien fait sur le sujet.

    a+

  6. #6
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 582
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 582
    Par défaut
    Citation Envoyé par hwoarang
    Un objet est détruit si et seulement si il n'est plus référencé.
    Un objet est éligible pour destruction si et seulement si il n'est accessible à aucun thread vivant.
    Et cela aboutit donc à ta conclusion : le thread étant vivant et ayant accès à l'instance de la classe mère, comment celle-ci pourrait-elle être détruite ?
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  7. #7
    Membre averti
    Profil pro
    Inscrit en
    Décembre 2009
    Messages
    31
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Décembre 2009
    Messages : 31
    Par défaut
    Merci pour vos réponses.

    J'ai bien lu le "synchronised" et le concept de thread-safe.

    Par contre, j'ai une lacune au niveau du comportement d'un objet utilisé par plusieurs Thread...

    Typiquement, imaginons un objet A instancié dans le thread principal (main()). On crée deux autres Thread (2 et 3) auxquels on passe la référence de l'objet A. Si les Thread 2 et 3 lisent en même temps la même variable de l'objet A, j'imagine qu'il y a pas de problème? Et si ils appellent la même méthode (elle n'écrit rien, juste lecture de variable + calcule + retourne une valeur), est-ce qu'ils peuvent le faire en même temps?

    Car pour moi, au niveau de la mémoire, j'ai de la peine à m'imaginer que deux Thread puissent accéder au même objet en même temps, je sais pas pourquoi...

    Justement, est-ce que l'objet A est copier et chaque Thread a le sien? C'est-a-dire qu'ils appellent chacun la même méthode qui est situé à deux endroits différent dans la mémoires? Ou est-ce que le faite que l'objet A vive dans le Thread principal fait que les Thread 2 et 3 ne peuvent exécuter la même méthode que l'un après l'autre?


    Merci beaucoup pour vos éclaircissements

  8. #8
    Expert éminent
    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
    Billets dans le blog
    1
    Par défaut
    Car pour moi, au niveau de la mémoire, j'ai de la peine à m'imaginer que deux Thread puissent accéder au même objet en même temps, je sais pas pourquoi...
    C'est tout à fait possible et cela ne pose aucun problème du moment qu'il n'y a que des opérations en lecture. C'est pour cela d'ailleurs qu'on peut partager sans soucis les objets immuables (String, Integer, Double, etc.)


    Mais dès que tu partage un objet "muable", tu peux encourir divers problème à partir du moment où il serait "modifié", même si c'est par un seul thread.

    Tu peux te retrouver dans des états incohérents, ou ne pas détecter le changement...



    a++

  9. #9
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 582
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 582
    Par défaut
    Citation Envoyé par gagou7 Voir le message
    Typiquement, imaginons un objet A instancié dans le thread principal (main()). On crée deux autres Thread (2 et 3) auxquels on passe la référence de l'objet A. Si les Thread 2 et 3 lisent en même temps la même variable de l'objet A, j'imagine qu'il y a pas de problème?
    Pas s'il n'y a que ça en tout cas. Mais si jamais un thread (l'un d'eux ou n'importe quel autre,) peut aussi écrire dans cette variable et pas seulement lire, là ça pose un problème.

    Citation Envoyé par gagou7 Voir le message
    Et si ils appellent la même méthode (elle n'écrit rien, juste lecture de variable + calcule + retourne une valeur), est-ce qu'ils peuvent le faire en même temps?
    Même chose qu'au-dessus, ce n'est qu'une question de lire les variables.

    Citation Envoyé par gagou7 Voir le message
    Car pour moi, au niveau de la mémoire, j'ai de la peine à m'imaginer que deux Thread puissent accéder au même objet en même temps, je sais pas pourquoi...
    Je sais pas quoi te dire. Les objets sont dans la mémoire, il y a plusieurs threads qui ont tous accès à la même mémoire, donc il y a plusieurs threads qui peuvent accéder au même objet. En cas de lecture/écriture c'est effectivement problématique et il faut synchroniser. En cas de lecture seule, pas de problème.

    Citation Envoyé par gagou7 Voir le message
    Justement, est-ce que l'objet A est copier et chaque Thread a le sien?
    Non. Si tu veux que chaque Thread ait une copie, rien ne t'empêche de faire une copie pour chaque Thread et de lui donner cette copie.

    Citation Envoyé par gagou7 Voir le message
    C'est-a-dire qu'ils appellent chacun la même méthode qui est situé à deux endroits différent dans la mémoires?
    Quoi ? Une méthode n'est pas une donnée, c'est un programme exécutable. Même s'il y avait plusieurs copies d'objet, toutes les instances d'objet passent par le même endroit pour exécuter la même méthode.

    (Et de toute façon, il n'y a pas de copie d'objet. Pas sans en faire une toi-même en tout cas.)

    Citation Envoyé par gagou7 Voir le message
    Ou est-ce que le faite que l'objet A vive dans le Thread principal fait que les Thread 2 et 3 ne peuvent exécuter la même méthode que l'un après l'autre?
    Peu importe par quels Threads l'objet A est accessible ou pas, les règles restent toujours les mêmes. Tous les Threads peuvent exécuter la méthode en même temps.
    Sauf si elle est synchronized, auquel cas, un seul Thread peut le faire à la fois parmi tous les Threads existants, quels qu'ils soient. Donc s'il y en a plusieurs qui arrivent en même temps, ils passent chacun leur tour.

    Du coup, s'il ne faut pas que la méthode soit exécutée par plusieurs threads en même temps (par exemple parce qu'elle fait des lectures/écritures,) il faut qu'elle soit synchronized. (Ou que tu t'assures qu'un seul thread l'appelle, bien sûr.)
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

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

Discussions similaires

  1. Réponses: 5
    Dernier message: 09/04/2014, 09h55
  2. MySQL n'est pas reconnu en tant que commande interne
    Par momobulle dans le forum Installation
    Réponses: 4
    Dernier message: 14/03/2012, 22h58
  3. Réponses: 3
    Dernier message: 23/09/2007, 13h50
  4. [Thread] Erreur dans une classe interne
    Par totof2308 dans le forum Général Java
    Réponses: 5
    Dernier message: 03/06/2004, 08h15

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