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 :

L'application se plante au niveau de la déclaration du bloc Synchronized


Sujet :

Langage Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé Avatar de JQueen
    Inscrit en
    Octobre 2008
    Messages
    214
    Détails du profil
    Informations personnelles :
    Âge : 38

    Informations forums :
    Inscription : Octobre 2008
    Messages : 214
    Par défaut L'application se plante au niveau de la déclaration du bloc Synchronized
    Bonjour à toutes et à tous,

    J'ai une application web qui permet de faire pleins de trucs dont l'insertion de données en base.

    Au niveau de l'implémentation de la méthode d'insertion, il y a un bloc synchronized qui contient des instructions "critiques" qui ne doivent être exécutées que par un seul thread à la fois.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    public void inserer(Personne personne, Connection connexion){
     
              //des instructions
     
              synchronized (MaClasse.class) {
                      //instructions critiques
              }
     
    }
    Je ne peux pas donner le code car c'est confidentiel.

    Ma question est : normalement le bloc synchronized est censé gérer l'accès concurrent des threads, et donc être exécuté à la fois par un seul thread et faire attendre les autres. Le comportement que j'ai remarqué est que l'application se plante au niveau du mot synchronized, elle n'entre même pas dans le bloc, est-ce un comportement normal ? Quelles sont les raisons possibles pour un tel comportement ?

    Merci

  2. #2
    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
    Hello,

    ben non, ce n'est pas normal.
    Mais pour en dire plus, il faudrait qu'on sache ce que veut dire "se planter", et comment diable t'y es-tu pris pour déterminer que ça arrive ici et pas ailleurs.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  3. #3
    Membre confirmé Avatar de JQueen
    Inscrit en
    Octobre 2008
    Messages
    214
    Détails du profil
    Informations personnelles :
    Âge : 38

    Informations forums :
    Inscription : Octobre 2008
    Messages : 214
    Par défaut
    Mais pour en dire plus, il faudrait qu'on sache ce que veut dire "se planter"
    L'application est bloquée au niveau de ce bloc et on ne peut plus rien faire si on ne redemarre pas le serveur tomcat.


    comment diable t'y es-tu pris pour déterminer que ça arrive ici et pas ailleurs.
    Je me suis servis des "logs", j'ai mis des logs partout dans la méthode d'insertion, notamment un juste avant le mot synchronized et un juste au début du bloc, comme suit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    log.info("insertion personne : début bloc synchronized");
    synchronized (MaClasse.class){
           log.info("insertion personne : début bloc synchronized");
           //instructions
    }
    En regardant ce qui est affiché dans la console, uniquement le 1er log est affiché. D'ailleurs l'affichage niveau console s'arrête au niveau de ce log là, voilà comment je sais qu'il n'entre pas dan le bloc et bloque vraiment au niveau de ce mot.

    J'ai oublié de mentionner que , pour tester, j'ai remplacer le mot synchronized par un boolean :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    public void inserer(Personne personne, Connection connexion){
     
              //des instructions
              boolean access = false;
              if (access == false) {
                       access = true;
                      //instructions critiques
                       access = false;
              }
     
    }
    L'application fait l'insertion sans aucun problème, mais je ne suis pas sûre dans ce cas est ce que l'insertion s'est faite correctement ou pas.

  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
    Salut,


    S'il ne rentre pas dans le bloc synchronized il n'y a qu'une seule raison : un autre thread possède déjà ce lock.
    Ce lock est-il utilisé autre-part ?


    a++

  5. #5
    Modérateur
    Avatar de Gugelhupf
    Homme Profil pro
    Analyste Programmeur
    Inscrit en
    Décembre 2011
    Messages
    1 326
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Analyste Programmeur

    Informations forums :
    Inscription : Décembre 2011
    Messages : 1 326
    Billets dans le blog
    12
    Par défaut
    Citation Envoyé par JQueen Voir le message
    J'ai oublié de mentionner que , pour tester, j'ai remplacer le mot synchronized par un boolean :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    public void inserer(Personne personne, Connection connexion){
     
              //des instructions
              boolean access = false;
              if (access == false) {
                       access = true;
                      //instructions critiques
                       access = false;
              }
     
    }
    L'application fait l'insertion sans aucun problème, mais je ne suis pas sûre dans ce cas est ce que l'insertion s'est faite correctement ou pas.
    accessest une variable locale, de ce fait ton bloc if sera toujours exécuté.
    Est-ce que ta classe est static ? Je demande ça parce que tu poses un verrou sur MaClasse.class alors que tu aurais par exemple pu le faire sur this.
    Est-ce que ton synchronized contient une autre méthode contenant un synchronized ?
    N'hésitez pas à consulter la FAQ Java, lire les cours et tutoriels Java, et à poser vos questions sur les forums d'entraide Java

    Ma page Developpez | Mon profil Linkedin | Vous souhaitez me contacter ? Contacter Gokan EKINCI

  6. #6
    Membre confirmé Avatar de JQueen
    Inscrit en
    Octobre 2008
    Messages
    214
    Détails du profil
    Informations personnelles :
    Âge : 38

    Informations forums :
    Inscription : Octobre 2008
    Messages : 214
    Par défaut
    Bonjour,

    S'il ne rentre pas dans le bloc synchronized il n'y a qu'une seule raison : un autre thread possède déjà ce lock.
    Ce lock est-il utilisé autre-part ?
    J'ai oublié de mentionner que ma classe MaClasse est un singleton :
    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
     
    public class MaClasse{
            ...
            /** instance. */
            private static MaClasse instance = null;
     
     
            public static MaClasse getInstance()
            {
                if (instance == null)
                {
                      synchronized (MaClasse.class)
                     {
                           if (instance == null)
                           {
                            instance = new MaClasse ();
                     }
                }
            }
            return instance;
        }
    Ca aide ?

    Est-ce que ta classe est static ? Je demande ça parce que tu poses un verrou sur MaClasse.class alors que tu aurais par exemple pu le faire sur this.
    Ma classe est un singleton. J'ai essayé d'utiliser le mot clé this à la place de la classe mais ça n'a rien changé.

    Est-ce que ton synchronized contient une autre méthode contenant un synchronized ?
    Non, mon synchronized ne contient aucun autre bloc synchronized.

    Merci.

  7. #7
    Modérateur
    Avatar de Gugelhupf
    Homme Profil pro
    Analyste Programmeur
    Inscrit en
    Décembre 2011
    Messages
    1 326
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Analyste Programmeur

    Informations forums :
    Inscription : Décembre 2011
    Messages : 1 326
    Billets dans le blog
    12
    Par défaut
    EDIT: Ce message contient une erreur.

    Message d'origine :


    Ton bloc synchronized peut indirectement contenir un autre bloc synchronized si ce dernier est situé dans une méthode qu'il appelle.

    Exemple :
    Code Java : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    public void methode1(){
        synchronized(MaClasse.class){}
    }
     
    public void methode2(){
        synchronized(MaClasse.class){
            methode1();
        }
    }

    Exécuter methode2 provoquera un deadlock.
    N'hésitez pas à consulter la FAQ Java, lire les cours et tutoriels Java, et à poser vos questions sur les forums d'entraide Java

    Ma page Developpez | Mon profil Linkedin | Vous souhaitez me contacter ? Contacter Gokan EKINCI

  8. #8
    Membre confirmé Avatar de JQueen
    Inscrit en
    Octobre 2008
    Messages
    214
    Détails du profil
    Informations personnelles :
    Âge : 38

    Informations forums :
    Inscription : Octobre 2008
    Messages : 214
    Par défaut
    Gugelhupf, Je pense que tu devrais le laisser à son mode par défaut
    C'est quoi le mode par défaut ? Est-il toujours le même ? Pourquoi a ton avis il faut garder ce mode ?


    en regardant la doc : http://www.java2s.com/Code/JavaAPI/j...onintlevel.htm, je remarque qu'on fait ce qui suit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    connexion.setTransactionIsolation(connexion.getMetaData().getDefaultTransactionIsolation());
    Je ne vois vraiment pas l'utilité de cette instruction

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

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

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    Citation Envoyé par JQueen Voir le message
    Du coup, ma question est : est ce qu'il faut modifier le code comme suit pour garantir la bonne gestion de transactions concurrentes ?
    Ca dépend de tes besoins d'isolation, de ce que tu veux garantir dans ta db. Vu que tu utilise une datasource, pas besoin de code, en général il y a une option de configuration directement dans la définition de la datasource.


    Citation Envoyé par JQueen Voir le message
    C'est quoi le mode par défaut ? Est-il toujours le même ? Pourquoi a ton avis il faut garder ce mode ?
    Le mode par défaut dépends du SGBD.
    Citation Envoyé par JQueen Voir le message


    Je ne vois vraiment pas l'utilité de cette instruction
    Revenir à la valeur par défaut. Ca a peu d'intérêt pour un usage courant, le datasource est supposé faire ce boulot.

  10. #10
    Membre confirmé Avatar de JQueen
    Inscrit en
    Octobre 2008
    Messages
    214
    Détails du profil
    Informations personnelles :
    Âge : 38

    Informations forums :
    Inscription : Octobre 2008
    Messages : 214
    Par défaut
    Bonjour,

    Vu que tu utilise une datasource, pas besoin de code, en général il y a une option de configuration directement dans la définition de la datasource.
    Voilà comment je défini ma datasource dans mon fichier context.xml:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
       <Resource name="jdbc/dataSource" auth="Container" type="javax.sql.DataSource"
                   maxActive="100" maxIdle="30" maxWait="10000"
                   username="user" password="pwd" driverClassName="oracle.jdbc.driver.OracleDriver"
                   url="jdbc:oracle:thin:@xxx.xx.xx.xx:xxx"/>
    C'est à ce moment là que je configure le mode d'isolation de transaction ? comme suit :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    <Resource name="jdbc/dataSource" auth="Container" type="javax.sql.DataSource"
                   maxActive="100" maxIdle="30" maxWait="10000"
                   username="user" password="pwd" driverClassName="oracle.jdbc.driver.OracleDriver"
                   transaction-isolation="TRANSACTION_SERIALIZABLE"
                   url="jdbc:oracle:thin:@xxx.xx.xx.xx:xxx"/>

  11. #11
    Modérateur
    Avatar de Gugelhupf
    Homme Profil pro
    Analyste Programmeur
    Inscrit en
    Décembre 2011
    Messages
    1 326
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Analyste Programmeur

    Informations forums :
    Inscription : Décembre 2011
    Messages : 1 326
    Billets dans le blog
    12
    Par défaut
    Citation Envoyé par JQueen Voir le message
    C'est quoi le mode par défaut ? Est-il toujours le même ? Pourquoi a ton avis il faut garder ce mode ?
    C'est l'un des 4 modes proposés par ton SGBD (ton SGBD peut en proposer moins). Celui d'Oracle (que tu sembles utiliser), ainsi que PostgreSQL, SQL Server et DB2 est Read Committed par défaut, celui de MySQL est Repeateable Read. Je garderais le mode par défaut pour une question de performance par rapport à mon besoin, donc soit je suis dans un environnement multi-utilisateur et ces utilisateurs ne modifient pas et ne font pas de lectures multiples sur un bloc de tuples durant leur transaction, soit je ne suis pas sur ce type d'environnement (ex: je fais la lecture de stats dans ma base que je considère comme un datawarehouse et il n'y a qu'un batch qui écrit de nuit).

    L'inconvénient du mode Read Committed est que si tu as une première transaction qui modifie la table et une autre transaction qui lit plusieurs fois cette même table durant sa transaction (par exemple une première lecture avant et une seconde lecture après que l'autre transaction ait committé), tu peux te retrouver avec une incohérence (lectures des "mêmes" données qui ont étés modifiés). C'est donc à toi d'évaluer si cas arrive dans ton application. En ce qui me concerne 1 besoin = 1 requête SELECT, donc je ne pas censé rencontrer ce type de problème.

    Si tu utilises <Resource> c'est que tu travailles dans un environnement où tu peux faire de l'injection de dépendance avec @Resource, autant en profiter
    N'hésitez pas à consulter la FAQ Java, lire les cours et tutoriels Java, et à poser vos questions sur les forums d'entraide Java

    Ma page Developpez | Mon profil Linkedin | Vous souhaitez me contacter ? Contacter Gokan EKINCI

  12. #12
    Membre confirmé Avatar de JQueen
    Inscrit en
    Octobre 2008
    Messages
    214
    Détails du profil
    Informations personnelles :
    Âge : 38

    Informations forums :
    Inscription : Octobre 2008
    Messages : 214
    Par défaut
    A notter qu'il n'est pas vraiment recommandé d'avoir besoin d'un synchonized pour manipuler tes données, t'as surement un plus gros problème de design si tu a besoin d'avoir recours à ça. Les connecteur type jdbc n'ont pas besoin de ça.
    Tu veux dire, que quand on essaye d'insérer/modifier des données en base , notamment la même, c'est le SGBD qui va gérer la cohérence de données, et du coup pas besoin de gérer l'accès concurrent niveau java, c ça ?

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

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

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    C'est à ça que sert l'isolation des transactions au niveau du SGBD oui. Si tu active le niveau SERIALIZABLE, le sgbd te garantis que deux transaction simultanées auront un résultat identique à si les deux transactions avaient eu lieu l'une à la suite de l'autre, peux importe l'ordre. Si ce n'est pas possible de le garantir, l'une des transaction échouera.

Discussions similaires

  1. [WD15] Application qui plante uniquement sur un poste
    Par mik3.42 dans le forum WinDev
    Réponses: 3
    Dernier message: 09/04/2010, 09h38
  2. Thread et application qui plante
    Par Balbuzard dans le forum Général Java
    Réponses: 10
    Dernier message: 29/08/2008, 16h36
  3. Réponses: 4
    Dernier message: 13/07/2008, 19h55
  4. Application qui plante à cause des tabs ?
    Par astrolus dans le forum Windows Forms
    Réponses: 1
    Dernier message: 02/05/2008, 22h54
  5. Application qui plante quand lancé par sans débugage
    Par bossun dans le forum Général Dotnet
    Réponses: 9
    Dernier message: 12/07/2007, 12h08

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