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 :

sur les threads


Sujet :

Java

  1. #1
    Membre confirmé
    Inscrit en
    Février 2009
    Messages
    85
    Détails du profil
    Informations forums :
    Inscription : Février 2009
    Messages : 85
    Par défaut sur les threads
    bonjour tout le monde,
    soit le programme java suivant:
    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
     
    package tp8;
     
    public class Testesync implements Runnable{
    private int balance;
    	public static void main(String[] args) {
    		Testesync obj = new Testesync();
    		Thread t = new Thread(obj);
    		Thread tt = new Thread(obj);
    		t.setName("Thread 1");
    		tt.setName("Thread 2");
    		t.start();
    		tt.start();
     
    	}
    	public void run(){
    	for(int i = 0;i<5;i++){
    		incrementer();
    		System.out.println(Thread.currentThread().getName()+" balance is :"+balance);
    	}
     
    	}
    	void incrementer(){
    		int i = balance;
    		balance = i+1;
    	}
     
    }
    l'exécution de ce programme donne:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    Thread 1 balance is :1
    Thread 1 balance is :3
    Thread 1 balance is :4
    Thread 1 balance is :5
    Thread 1 balance is :6
    Thread 2 balance is :2  // ????
    Thread 2 balance is :7
    Thread 2 balance is :8
    Thread 2 balance is :9
    Thread 2 balance is :10
    quelqu'un peut m'expliquer ce résultat. notamment : Thread 2 balance is :2
    si un thread est bloqué par la JVM , est ce qu'il fait la sauvgarde de l'état de ses variables (mème partagés). si oui au reprend il consulte l'état des variables sauvgardé et non pas les nouveaux états, n'est ce pas?
    remarque: je sais pour résoudre ce type de problème je dois utiliser synchronized.
    merci d'avance.

  2. #2
    Membre Expert
    Avatar de professeur shadoko
    Homme Profil pro
    retraité nostalgique Java SE
    Inscrit en
    Juillet 2006
    Messages
    1 257
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 76
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : retraité nostalgique Java SE

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 257
    Par défaut
    exemple de considérations annexes sur ce problème : sur le modèle mémoire

  3. #3
    Membre Expert Avatar de Uther
    Homme Profil pro
    Tourneur Fraiseur
    Inscrit en
    Avril 2002
    Messages
    4 690
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pyrénées Orientales (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Tourneur Fraiseur

    Informations forums :
    Inscription : Avril 2002
    Messages : 4 690
    Par défaut
    En effet l'état des variables accédée par deux thread différents peuvent poser ce genre de surprises.
    C'est du aux optimisations que ce permet le programme. Pour les interdire, il faut les déclarer "volatile".

  4. #4
    Membre confirmé
    Homme Profil pro
    Développement logiciel
    Inscrit en
    Mai 2005
    Messages
    74
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développement logiciel
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Mai 2005
    Messages : 74
    Par défaut
    Tes 2 thread sont construits à partir du même objet "Testesync", donc la valeur "balance" de cet objet sera accédée par les 2 threads simultanément. Jusque là, pas de pb.

    Le fait que les valeurs de "balance" ne soient pas affichées dans un ordre croissant ne signifie pas qu'il y a un bug, mais simplement que l'affichage ne se rafraichit pas forcément à chaque fois qu'un thread y accède. L'affichage peut "bufferiser" certaines lignes concernant un thread et les relacher quand l'autre thread rend la main.

    Si tu veux afficher les valeurs de "balance" dans l'ordre croissant, il faut effectivement utiliser le mot clé synchronized, et vider le buffer d'affichage ainsi:

    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
    public class Testesync implements Runnable{
    	private volatile int balance = 0;
    	public static void main(String[] args) {
    		Testesync obj = new Testesync();
    		Thread t = new Thread(obj);
    		Thread tt = new Thread(obj);
    		t.setName("Thread 1");
    		tt.setName("Thread 2");
    		t.start();
    		tt.start();
     
    	}
    	public void run(){
    		for(int i = 0;i<5;i++){
    			incrementer();
    		}
    	}
     
    	public synchronized void incrementer()
    	{
    		balance++;
    		System.out.println(Thread.currentThread().getName()+" balance is :"+balance);
    		System.out.flush();
    	}
     
    }
    Le mot clé volatile, sert à s'assurer que le système met bien à jour la valeur de "balance" lorsqu'un thread y accède.

  5. #5
    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
    ca prouve juste que ton thread 2 a été bloqué entre le moment ou il a construit la string "Thread 2 balance is :2" et le moment ou il a appelé System.out.println() avec. T'as encor de la chance, balance n'est pas été corrompu, si ton thread avait été interrompu entre les deux instructions de incrementer, t'aurais pus avoir des doublons, genre


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    Thread 1 balance is :1
    Thread 1 balance is :2
    Thread 2 balance is :2 
    Thread 2 balance is :3 
    Thread 2 balance is :4
    Thread 1 balance is :3
    Thread 2 balance is :4
    Thread 1 balance is :5

  6. #6
    Membre confirmé Avatar de samaury
    Homme Profil pro
    Chevalier Jedi
    Inscrit en
    Mars 2008
    Messages
    114
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Côte d'Ivoire

    Informations professionnelles :
    Activité : Chevalier Jedi
    Secteur : Finance

    Informations forums :
    Inscription : Mars 2008
    Messages : 114
    Par défaut
    Citation Envoyé par egann538 Voir le message
    Tes 2 thread sont construits à partir du même objet "Testesync", donc la valeur "balance" de cet objet sera accédée par les 2 threads simultanément. Jusque là, pas de pb.....
    J'ai peur de (ne pas) comprendre. Es-tu en train de dire que les deux threads accèdent à la même référence de "balance"? Du coup quand Thread 1 modifie "balance" Thread 2 voie cette modification?

  7. #7
    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 samaury Voir le message
    Es-tu en train de dire que les deux threads accèdent à la même référence de "balance"? Du coup quand Thread 1 modifie "balance" Thread 2 voie cette modification?
    Ben oui puisque tu n'as qu'une seule et unique instance de la classe Testesync. Tu n'as donc qu'un seul "balance"...


    Après tu obtiens des résultats aléatoire car tu manipules les mêmes données depuis différents threads sans synchronisation.
    Du coup tu peux avoir des comportements aléatoire...


    En fait il y a une synchronisation (sur System.out) mais elle n'englobe pas tout ton traitement.


    a++

  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 : 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 samaury Voir le message
    J'ai peur de (ne pas) comprendre. Es-tu en train de dire que les deux threads accèdent à la même référence de "balance"? Du coup quand Thread 1 modifie "balance" Thread 2 voie cette modification?
    en réalité, "Thread1" et "Thread2" (les objets donc) n'ont pas accès à balance. C'est le run() d'une seule instance de TesteSync qui fonctionne deux fois en parallèle, et donc forcément avec les même champs

  9. #9
    Membre confirmé
    Inscrit en
    Février 2009
    Messages
    85
    Détails du profil
    Informations forums :
    Inscription : Février 2009
    Messages : 85
    Par défaut
    bonjour,
    merci pour vos réponses;
    si j'ai bien compris c'est un problème de visibilié (utiliser un registre pour stocker le resultat ...), reordonner les instructions par le compilateur,etc.
    voici un nouveau problème, cette fois ci avec synchronized.
    cas 1: code précedant (toujours avec Runnable)+ synchronized:
    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
     
    package tp8;
     
    public class Testesync implements Runnable{
    private  int balance;
    	public static void main(String[] args) {
    		Testesync obj = new Testesync();
    		Thread t1 = new Thread(obj);
    		Thread t2 = new Thread(obj);
    		t1.setName("Thread 1");
    		t2.setName("Thread 2");
    		t1.start();
    		t2.start();
     
    	}
    	public void run(){
    	for(int i = 0;i<5;i++){
    		incrementer();
     
    	}
     
    	}
    	 synchronized void incrementer(){
     
    		int i = balance;
    		balance = i+1;
    		System.out.println(Thread.currentThread().getName()+" balance is :"+balance);
     
    	}
     
    }
    à la fin de l'exécution, j'obtiens toujours: rrrr balance is :10 ou rrrr est un des deux threads
    pour moi, c'est le résutat attendu

    cas 2: le mème programme mais cette fois-ci, j'ai utilisé la classe Thread:
    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
     
    package tp9;
     
    public class A extends Thread {
    private int balance;
     
    public void run(){
    	for(int i = 0;i<5;i++){
    		incrementer();
     
    	}
     
    	}
    	 synchronized void incrementer(){
     
    		int i = balance;
    		balance = i+1;
    		System.out.println(Thread.currentThread().getName()+" balance is :"+balance);
     
    	}
     
    }
    la classe de test:
    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
     
    package tp9;
     
    public class B {
     
     
    	public static void main(String[] args) {
    		A t1 = new  A();
    		A t2 = new  A();
    		t1.setName("Thread 1");
    		t2.setName("Thread 2");
    		t1.start();
    		t2.start();
     
    	}
     
    }
    j'obtiens un résultat bizarre, la variable balance n'a jamais atteint la valeur 10
    exemple d'exécution:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    Thread 1 balance is :1
    Thread 2 balance is :1
    Thread 1 balance is :2
    Thread 2 balance is :2
    Thread 1 balance is :3
    Thread 2 balance is :3
    Thread 1 balance is :4
    Thread 2 balance is :4
    Thread 1 balance is :5
    Thread 2 balance is :5
    question: quelqu'un peut m'exliquer pour quoi le resultat final dans cas 2 ne correspond pas au resultat dans cas 1 ?
    merci d'avance

  10. #10
    Membre Expert Avatar de herve91
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    1 282
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 1 282
    Par défaut
    Parce que cette fois chaque instance de thread t1 et t2 dispose de sa propre "balance". Avant tu n'instanciais qu'une seule fois Testesync, donc la variable "balance" était partagée par les threads. A présent tu as deux instances de A, chacune disposant de son propre attribut "balance".

Discussions similaires

  1. Quelques questions sur les threads
    Par benj63 dans le forum C++Builder
    Réponses: 28
    Dernier message: 21/11/2005, 13h27
  2. Question sur les threads
    Par Linio dans le forum Concurrence et multi-thread
    Réponses: 10
    Dernier message: 21/10/2005, 09h08
  3. Question sur les threads
    Par nicolas66 dans le forum MFC
    Réponses: 4
    Dernier message: 03/06/2005, 20h57
  4. Aide sur les Threads
    Par themoye dans le forum MFC
    Réponses: 24
    Dernier message: 06/03/2005, 15h02
  5. Question simple sur les threads :)
    Par momox dans le forum C++Builder
    Réponses: 2
    Dernier message: 15/06/2003, 04h13

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