[synchronized]quand et pourquoi l'utiliser

Résolu
ajp55 Messages postés 426 Date d'inscription   Statut Membre Dernière intervention   -  
ajp55 Messages postés 426 Date d'inscription   Statut Membre Dernière intervention   -
Bonjour,
je suis nouveau dans le developpement java et j'ai vu dans certain fonction on ajoutais synchronized devant le nom de la fonction. j'ai parcouru la doc java mais je n'arrive toujours pas à comprendre ce qui peut bien me pousser à utiliser un tel mot.
quelqu'un peut-il m'expliquer quand faut -il exactement utiliser ce mot clé de java?
Merci d'avance pour vos réponses. j'en serai très ravi.





"L'ordinateur est une grande invention : il y a autant d'erreur qu'avant mais plus personne n'est responsable..."
A voir également:

1 réponse

KX Messages postés 16761 Date d'inscription   Statut Modérateur Dernière intervention   3 020
 
Un programme Java peut exécuter plusieurs threads, ce sont des fils d'exécutions qui se déroulent en parallèle (c'est à dire "en même temps").

Prenons un exemple : tu as deux threads qui font la même chose en même temps.
Ils lisent la valeur de "n", lui ajoute 1, et stocke le résultat dans "m".
Puis ils attendent un petit peu (pour simuler une charge de travail)
Enfin, ils mettent à jour "n" avec la valeur de "m", et affiche la nouvelle valeur.
Les deux Threads recommencent chacun cette opération 100 fois.

public class Test 
{
    public static Integer n=0;
    
    static class Ajout extends Thread
    {
        private static void add()
        {
            int m = n + 1;
            try { Thread.sleep(0,1); } catch (InterruptedException e) { }
            n = m;
            System.out.println(n);
        }
        
        @Override
        public void run()
        {
            for (int i=0; i<100; i++)
                add();
        }
    }
        
    public static void main(String[] args)
    {
        Ajout a1 = new Ajout();
        Ajout a2 = new Ajout();
        
        a1.start();
        a2.start();
    }
}

Le résultat attendu pour ce calcul est donc de voir s'afficher 1, 2, 3, 4... 199, et 200.
Or ce n'est pas cela qu'on obtient !
En effet, les deux threads s'exécutent en parallèle, mais ils se partagent la même variable de n, il peut donc y avoir des conflits.

Exemple : le premier thread lit "n=12" ce qui donne "m=13". Mais en même temps, le deuxième thread lit lui aussi "n=12" ce qui donne aussi "m=13". Ils vont donc tous les deux mettre à jour "n" avec la valeur 13, alors que l'on aurait voulu avoir 14.

Comment résoudre le problème ?
Tout simplement en ajoutant le mot clé "synchronized" à la méthode add, cela va restreindre l'accès à la méthode à un seul thread à la fois. Si un thread est en train d'exécuter la méthode add, le deuxième thread qui va vouloir y rentrer va être mis en attente jusqu'à ce que le premier thread est terminé, à ce moment là le deuxième thread va être autorisé à rentrer dans la méthode add, et va à son tour la bloquer pour son usage unique.
Comme il n'y a plus de conflit, les deux threads manipuleront toujours les bonnes valeurs de "n" et on aura bien un affichage jusqu'à n=200.
1
ajp55 Messages postés 426 Date d'inscription   Statut Membre Dernière intervention   23
 
Merci pour ton aide, maintenant je comprend mieux à quoi ça sert. le plus souvent lorsque les ressources sont partagés par plusieurs Thread (utilisation du mot clé static j'espère), on utilise synchronized pour bloqué la ressource aux autres pendant que l'un utilise la ressource.
Merci.
0
KX Messages postés 16761 Date d'inscription   Statut Modérateur Dernière intervention   3 020
 
"les ressources sont partagés par plusieurs Thread (utilisation du mot clé static j'espère)"
Le mot clé static n'a aucun rapport avec l'utilisation des threads ou la synchronisation, il sert juste à indiquer qu'il s'agit d'objet (ex: n), de méthode (ex: add), ou de classe (ex: Ajout) qui s'utilisent indépendamment de tout objet.

Alors effectivement ça va parfois ensemble, mais ce n'est pas systématique !
Voici un exemple, qui fait à peu près la même chose, mais sans utiliser le mot-clé static :

public class Entier
{
    private int n;
    
    public /*synchronized*/ void inc()
    {
        n++;
    }
        
    public String toString()
    {
        return String.valueOf(n);
    }
}

public class Ajout extends Thread
{
    private final int id;
    private final Entier ent;
    
    public Ajout(int id, Entier ent)
    {
        this.id = id;
        this.ent = ent;        
    }
    
    @Override
    public void run()
    {
        String start = ent.toString();
        
        for (int i=0; i<1000000; i++)
            ent.inc();
        
        String end = ent.toString();
        
        System.out.printf("Le thread %d a commencé avec n=%s et termine avec n=%s\n", id, start, end);
    }
}

public class Test 
{            
    public static void main(String[] args)
    {
        Entier ent = new Entier();
        
        for (int id=0; id<5; id++)
            new Ajout(id,ent).start();
    }
}
0
ajp55 Messages postés 426 Date d'inscription   Statut Membre Dernière intervention   23
 
Bien compris et merci
0