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 :

Synchronisation des threads


Sujet :

Java

  1. #1
    Membre actif
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    294
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 294
    Points : 268
    Points
    268
    Par défaut Synchronisation des threads
    Bonjour, j'ai besoin d'utiliser la synchronisation dans mes threads. Je me suis donc tourné vers des tuto proposé par www.developpez.net
    Voici le tuto que j'ai regardé Programmation des Threads en Java.

    Dans la partie 2 de ce tuto, j'ai essayé de réaliser la l'exemple mais la synchronisation ne marche pas pour moi.

    Voici le code que j'ai compilé:
    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
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    import java.util.Random;
     
    public class VaseComuniquant {
    	private static final int QUANTITE_INITIALE = 200;
    	private static final int NB_THREAD_MAX = 2;
     
    	private static int iteration = 0;
     
    	private int[] vase = { QUANTITE_INITIALE / 2, QUANTITE_INITIALE / 2 };
     
    	public VaseComuniquant() {
    		for (int i = 0; i < NB_THREAD_MAX; i++)
    			new ThreadTransfert().start();
    	}
     
    	public static void main(String[] args) {
    		new VaseComuniquant();
    	}
     
    	synchronized public int transfert(int qte) {
    		// Ne pas enlever les System.out de ce test !
    		System.out.print("-(" + qte + ") dans le vase 1 ");
    		vase[0] -= qte;
    		System.out.println("+(" + qte + ") dans le vase 2");
    		vase[1] += qte;
    		iteration++;
    		if (iteration % 1000 == 0)
    			System.out.println("" + iteration + " itérations.");
    		return vase[0] + vase[1];
    	}
     
    	public class ThreadTransfert extends Thread {
    		Random r = new Random();
    		int quantite;
     
    		public void run() {
    			while (!isInterrupted()) {
    				quantite = r.nextInt(11) - 6;
    				vase[0] -= quantite;
    				vase[1] += quantite;
    				if (transfert(quantite) != QUANTITE_INITIALE) {
    					System.err.println("Quantité totale invalide à l'itération " + iteration);
    					System.exit(-1);
    				}
     
    				try {
    					Thread.sleep(10);
    				} catch (InterruptedException e) {
    				}
    			}
    		}
     
    	}
    }
    Pouvez vous me dire d'ou vient le problème?

    Merci d'avance

  2. #2
    Membre éprouvé
    Inscrit en
    Mars 2006
    Messages
    848
    Détails du profil
    Informations personnelles :
    Âge : 40

    Informations forums :
    Inscription : Mars 2006
    Messages : 848
    Points : 1 078
    Points
    1 078
    Par défaut
    Bonjour,

    quand on fait du multi-thread, il faut bien repérer quelles sont les points sensibles : quels objets sont accédés par différents threads.

    Dans ce cas, c'est le tableau vase.

    La méthode transfert modifie vase, mais comme elle est synhcronizée, les différents appels se feront successivement et donc de manière thread-safe.

    En revanche, dans la boucle while, tu as une modification de vase qui n'est pas synchronisée, c'est là que se situe le problème.

  3. #3
    Membre actif
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    294
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 294
    Points : 268
    Points
    268
    Par défaut
    Donc l'exemple proposé dans le tuto n'est pas correcte.

    Voici un petit exemple que j'ai mis en place:

    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
     
    public class MonThread extends Thread {
     
    	String name;
     
    	public MonThread(String name) {
    		this.name = name;
    	}
     
    	@Override
    	public void run() {
    		maMethode(name);
    	}
     
    	synchronized public void maMethode(String name) {
    		System.out.println("Début du thread: " + name);
    		try {
    			Thread.sleep(5000);
    		} catch (InterruptedException e) {
    			e.printStackTrace();
    		}
    		System.out.println("Fin du thread: " + name);
    	}
     
    	public static void main(String[] args) {
     
    		for (int i = 0; i < 5; i++) {
    			MonThread monThread = new MonThread("thread" + i);
    			monThread.start();
    		}
     
    	}
     
    }
    et voici le résultat que j'obtiens:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    Début du thread: thread0
    Début du thread: thread2
    Début du thread: thread4
    Début du thread: thread1
    Début du thread: thread3
    Fin du thread: thread2
    Fin du thread: thread3
    Fin du thread: thread1
    Fin du thread: thread4
    Fin du thread: thread0
    pourtant la méthode que j'appelle est bien synchronized. Comment faire pour que les threads ne fassent pas appelle à cette méthode en meme temps?

  4. #4
    Expert éminent sénior
    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
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Salut,

    Citation Envoyé par tupac25 Voir le message
    pourtant la méthode que j'appelle est bien synchronized.
    Dans ce cas précis tu as une méthode d'instance. Donc la synchronisation se fait logiquement sur l'instance de l'objet. Comme tu en a 5 chaque thread travaille sur sa propre instance et il n'y a pas de conflit...


    a++

  5. #5
    Membre actif
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    294
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 294
    Points : 268
    Points
    268
    Par défaut
    L'exemple du tuto se base aussi sur des instances différentes... Je n'ai donc pas d'autre choix que de mettre ma méthode en static?

    Voici ce qui est dit dans le tuto:
    Le mot-clé synchronized indique qu'un et un seul thread peu accéder en même temps à cette méthode. Ainsi, les données manipulées ne risquent pas d'être altérées.

    Les threads dont il est question sont bien des instances différentes.

  6. #6
    Expert éminent sénior
    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
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Oui mais dans l'exemple il y a 5 instances Threads différents qui manipule une seule et unique instance de l'objet VaseComuniquant.

    Donc les 5 threads manipules la même méthode de la même instance,ce qui n'est pas le cas de ton code...

    a++

  7. #7
    Membre actif
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    294
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 294
    Points : 268
    Points
    268
    Par défaut
    Merci pour ton aide, je vois mieux d'ou vient mon problème

    Sais-tu s'il y a un moyen de synchroniser des méthodes d'instances différentes?

  8. #8
    Expert éminent sénior
    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
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Oui : il faut utiliser le même objet comme lock sur la synchronisation... Mais quel intérêt à cela ????


    a++

    PS : Expliques plutôt ce que tu veux faire exactement...

  9. #9
    Membre actif
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    294
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 294
    Points : 268
    Points
    268
    Par défaut
    Je dois monitorer des queues recevant des message avec mon application. J'ai donc décider de mettre en place un thread par queue. Lorsqu'une alerte est déclenché par une queue, j'ai un systeme d'alerte qui est lancé uniquement pour la premiere alerte donc par la suite si une seconde queue entre en alerte, celle ci ne doit pas déclencher d'alerte.

    Pour éviter que mes threads lances 2 alertes en même temps, j'ai voulu synchroniser la méthode qui permet de lancer les alertes.

  10. #10
    Expert éminent sénior
    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
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Donc cette méthode d'alerte ne doit pas faire partie de tes Threads, mais d'une classe séparé dont tu n'aurait qu'une seule instance...


    a++

  11. #11
    Membre actif
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    294
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 294
    Points : 268
    Points
    268
    Par défaut
    Je suis d'accord mais le problème c'est que l'alerte ne doit etre déclaré qu'une seule fois mais elle peut venir de n'importe qu'elle thread. Pour le moment le code que j'ai mis en place marche mais il y a un risque de bug si deux thread font appelle à l'alerte en meme temps.

  12. #12
    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
    si la méthode d'alert est sur une objet unique partagé entre les threads, et qu'elle est synchronisée, un seul thread pourra l'appeler en même temps. A partir de là, il suffit dans le corps de la méthode d'alert de mettre un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if (dejaDeclencheParLePasse) return;
    Pour garantir une seule exécution au total du reste du code de la méthode.

  13. #13
    Membre actif
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    294
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 294
    Points : 268
    Points
    268
    Par défaut
    Merci pour votre aide. J'ai mis en place un objet partagé par mes threads. Ca résoud mon problème de conflit.

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

Discussions similaires

  1. synchronisation des thread
    Par gentelmand dans le forum Concurrence et multi-thread
    Réponses: 1
    Dernier message: 29/12/2007, 10h06
  2. synchronisation des thread
    Par gentelmand dans le forum Concurrence et multi-thread
    Réponses: 2
    Dernier message: 25/12/2007, 23h45
  3. [Thread] Synchroniser des threads
    Par GLDavid dans le forum Concurrence et multi-thread
    Réponses: 3
    Dernier message: 24/06/2006, 16h34
  4. Question sur la synchronisation des threads.
    Par sebastieng dans le forum Langages de programmation
    Réponses: 4
    Dernier message: 07/12/2005, 15h55

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