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] synchronised (MyObject.class)


Sujet :

Concurrence et multi-thread Java

  1. #1
    Membre éclairé
    Inscrit en
    Juin 2006
    Messages
    570
    Détails du profil
    Informations forums :
    Inscription : Juin 2006
    Messages : 570
    Par défaut [Thread] synchronised (MyObject.class)
    Bonjour,

    Dans une appli, un serveur va à chaque requête recu d'un client générer un thread pour la traiter.
    Ce thread utilise entre autre l'instruction suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    XPathFactory factory = XPathFactory.newInstance();
    XPathFactory.newInstance() n'étant pas synchronisé, il faut donc que je le fasse à mon niveau. Seulement je n'ai pas de mutex général.
    JE voulais donc savoir, si effectuer
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    synchronised(XpathFactory.class)
            factory = XPathFactory.newInstance();
    [/code]

    permettait cette synchro ? Ou s'il y avait plus simple/propre ?
    Utiliser par exemple une variable de class static servant de mutex est il plus propre ?

  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,


    Tu peux très bien utiliser la classe comme mutex. C'est même très propre à mon avis !
    D'ailleurs c'est ce qui est utilisé lorsque tu définis une méthode static synchronized...


    Par contre je ne pense pas qu'il y ait besoin de synchronisé les newInstance() !

    a++

  3. #3
    Membre éclairé
    Inscrit en
    Juin 2006
    Messages
    570
    Détails du profil
    Informations forums :
    Inscription : Juin 2006
    Messages : 570
    Par défaut
    D'accord merci.
    Par contre pourquoi penses tu qu'une synchro n'est pas nécessaire ?

    Je ne maitrise pas encore tous les concepts de synchro, mais quand je regarde le code de la fonction newInstance, elle me ne semble pas thread safe, si ?

    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
     
     
     public static final XPathFactory newInstance(final String uri)
            throws XPathFactoryConfigurationException {
     
            if (uri == null) {
            	throw new NullPointerException(
            		"XPathFactory#newInstance(String uri) cannot be called with uri == null"
            	);
            }
     
    		if (uri.length() == 0) {
    			throw new IllegalArgumentException(
    				"XPathFactory#newInstance(String uri) cannot be called with uri == \"\""
    			);
    		}
     
    		ClassLoader classLoader = ss.getContextClassLoader();
     
            if (classLoader == null) {            
                //use the current class loader
                classLoader = XPathFactory.class.getClassLoader();
            } 
     
    		XPathFactory xpathFactory = new XPathFactoryFinder(classLoader).newFactory(uri);
     
    		if (xpathFactory == null) {
    			throw new XPathFactoryConfigurationException(
    				"No XPathFactory implementation found for the object model: "
    				+ uri
    			);
    		}
     
    		return xpathFactory;
        }

  4. #4
    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 : 45
    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
    Qu'est-ce qui te fait penser que cette méthode n'est pas ThreadSafe. Elle ne modifie que des variables locales, et ne fait que des appels à new ou des appels au classloader.

  5. #5
    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 tchize_ Voir le message
    Qu'est-ce qui te fait penser que cette méthode n'est pas ThreadSafe. Elle ne modifie que des variables locales, et ne fait que des appels à new ou des appels au classloader.
    +1


    Un code thread-safe n'implique pas forcément une synchronisation.


    a++

  6. #6
    Membre éprouvé
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    104
    Détails du profil
    Informations personnelles :
    Âge : 48
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Mars 2004
    Messages : 104
    Par défaut
    Salut,

    la méthode newInstance() te renvoie une nouvelle instance (comme son nom l'indique) mais pas la même instance à chaque appel (ce n'est pas un singleton).
    Il n'y a pas besoin de synchroniser cette méthode pour ce fonctionnement.
    Après si tu veux un singleton, c'est à toi de gérer la création de cette instance mais aussi de vérifier que la classe XPathFactory est thread-safe

  7. #7
    Membre éclairé
    Inscrit en
    Juin 2006
    Messages
    570
    Détails du profil
    Informations forums :
    Inscription : Juin 2006
    Messages : 570
    Par défaut
    Ah bah, ca va me permettre de poser une question qui me tracasse depuis quelque temps ^^
    Dans une fonction static, les variables internes à la fonction ne sont pas partagée ? Si j'ai la fonction

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    public static void func(String str) {
        int a; 
        String str2;
    }
    Toutes les variables de cette fonction sont elles static également ?

    J'aurais été sur que non jusqu'il y a peu, où j'avais des soucis valeurs étrange lorsque j'utilisais un module en multithreadé. Ce module utilisant une bibliothèque de fonction static, dans le doute, j'ai passé toute ces fonctions en synchronised, et depuis plus rien.
    Après c'est peut être un pur hasard, ou un effet de bord sympathique.

  8. #8
    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 : 45
    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
    la notion de static s'applique uniquement à ce qui se trouve au niveau de la classe. Le variables dans les méthodes restent limitées au scope de la méthode. Elle sont stockée sur la pile d'appel et non pas dans la classe. Si ta classe posait problème c'est qu'elle manipulait des champs statique et non des variables locale. Le problème n'est d'ailleurs pas lié à l'aspect statique. Des méthodes non statiques peuvent aussi être non thread-safe.

  9. #9
    Membre éclairé
    Inscrit en
    Juin 2006
    Messages
    570
    Détails du profil
    Informations forums :
    Inscription : Juin 2006
    Messages : 570
    Par défaut
    Citation Envoyé par tchize_ Voir le message
    la notion de static s'applique uniquement à ce qui se trouve au niveau de la classe. Le variables dans les méthodes restent limitées au scope de la méthode. Elle sont stockée sur la pile d'appel et non pas dans la classe. Si ta classe posait problème c'est qu'elle manipulait des champs statique et non des variables locale. Le problème n'est d'ailleurs pas lié à l'aspect statique. Des méthodes non statiques peuvent aussi être non thread-safe.
    Elle manipule bien des variables static, mais uniquement en lecture, ce sont de toute façon des constantes. M' enfin ca devait être un effet de bord, je suppose qu'en les mettant toutes synchro je dois ralentir légèrement l'appli ce qui a permis une meilleur synchro. Bon va falloir que je revois cette partie là aussi alors

    Merci bien pour ces informations en tout cas.

  10. #10
    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
    Il faut distinguer deux choses :

    • La valeur des références/types primitifs
    • Le contenu des objets en eux-même.


    En ce qui concerne la valeur des références/types primitifs, le problème peut survenir lorsqu'un autre thread modifie la valeur de l'extérieur (depuis un autre thread). En effet dans ce cas le status est modifié sans que tu ne le saches, et ton code apparemment correct peut se retrouver dans un état incohérent.

    Prenons par exemple ce simple code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    public static String name = "fred";
     
    public void hello() {
    	if (name==null) {
    		System.out.println("Hello World !");
    	} else {
    		System.out.println("Hello " + name.toUpperCase() + " !");
    	}
    }
    Ce code semble tout à fait correct, mais l'utilisation d'un attribut le rend dangereux. En effet cet attribut peut être modifié depuis un autre thread et provoquer des erreurs ou provoqué des effets de bords...

    Imagine le cas suivant :
    1. name vaut "fred", tu appelles la méthode hello().
    2. la valeur du if est fausse, et tu rentres logiquement dans le else.
    3. Un autre thread prend la main, et met l'attribut name à null
    4. Ton thread reprend la main et génère une exception, puisque désormais name est null !


    Maintenant si comme dans ton exemple le code n'utilise QUE des variables locales ou ses paramètres, ce problème n'existe pas : les valeurs ne peuvent pas être modifié depuis l'extérieur et il n'y a aucun soucis !

    D'ailleurs la meilleure solution pour éviter ce type de problème est d'utiliser une référence locale AVANT de vérifier les données :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    public static String name = "fred";
     
    public void hello() {
    	String txt = name; // On copie la référence 
    	if (txt==null) {
    		System.out.println("Hello World !");
    	} else {
    		System.out.println("Hello " + txt.toUpperCase() + " !");
    	}
    }
    Les modifications sur la référence 'name' n'impacteront pas la variable locale 'txt', et donc notre code fonctionne désormais sans soucis quoi qu'on fassent sur l'attribut 'name'. Dans le pire des cas, si 'name' est modifié pendant l'exécution de notre méthode, on affichera la valeur précédente ce qui n'est pas si gênant en soit...


    Donc en clair :
    • Les variables locales et les paramètres sont protégés des affectations externes.
    • Les attributs (static ou d'instance) peuvent très bien être modifié de l'extérieur, et leurs accès doivent être protégés si on veut un code thread-safe.








    C'est là qu'on en arrive au second problème : Le contenu des objets en eux-même.
    Si mon dernier code fonctionne très bien, c'est que la classe String est immuable et thread-safe. On peut donc l'utiliser dans différents threads sans problème.

    Le problème c'est que ce n'est pas le cas de toutes les classes, et que bon nombre sont modifiable et pas forcément thread-safe.

    Dans ces cas là c'est toutes les utilisations des instances qui doivent être protégé si on compte y accéder depuis différents threads, et ceci généralement via la synchronisation... mais pas forcément !


    C'est difficile à détaillé car cela dépend vraiment du code et des types de données qui sont utilisé et comment... Sans code détaillé impossible de t'aider sur ce point !


    a++

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

Discussions similaires

  1. thread dédié à une classe pour lui "donner vie"
    Par Dje14 dans le forum Threads & Processus
    Réponses: 5
    Dernier message: 02/06/2005, 16h46
  2. Réponses: 1
    Dernier message: 23/05/2005, 15h52
  3. [Thread] synchronisation globale
    Par guejo dans le forum Concurrence et multi-thread
    Réponses: 6
    Dernier message: 16/02/2005, 11h56
  4. [Thread][Synchronisation] Exclusion mutuelle
    Par masto dans le forum Concurrence et multi-thread
    Réponses: 8
    Dernier message: 20/01/2005, 16h02
  5. Thread dans une classe ?
    Par Sephi dans le forum Threads & Processus
    Réponses: 7
    Dernier message: 07/03/2004, 18h16

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