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 :

Threads, consommateurs & producteurs, problème de synchronisation.


Sujet :

Java

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    13
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 13
    Points : 12
    Points
    12
    Par défaut Threads, consommateurs & producteurs, problème de synchronisation.
    Salut,

    Voilà j'essaye de faire une émulation de buffer (TP d'université). Je vous mets ci dessous une partie fonctionnelle incomplète (sachant que je gère aussi des délais fictifs d'attente pour chaque producteurs et consommateurs)

    Le buffer contient 4 espaces destinés à 4 lettres.

    Un producteur envoie en une lettre au buffer, si celui-ci est plein, le thread se met en attente (wait), sinon il l'insere en première position et décale les autres.

    Un consommateur extraie une lettre du buffer (il prend la 4ème si elle n'est pas nulle, ou 3ème, ou seconde ou première) mais si celui-ci est vide il se met en attente (wait).

    Le programme fonctionne lorsque j'ai:
    - 1 consommateur & 1 producteur
    - 2 consommateurs & 1 producteur

    Cela ne fonctionne pas lorsque j'ai:
    - 1 consommateur & 2 producteurs

    Voici mon code:

    Classe correspondant au buffer:
    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
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
     
    class Q {
    	int n;
     
    	String a = null;
    	String b = null;
    	String c = null;
    	String d = null;
     
    	synchronized String get() {
    		if(d==null && c==null && b==null && a==null)
    			try {
    				wait();
    			} catch(InterruptedException e) {
    				System.out.println("InterruptedException caught");
    			}
     
    			if(d!=null)
    			{
    				String temp = null;
    				temp = d;
    				d = null;
    				notify();
    				System.out.println("Got: " + temp);
    				return temp;				
    			}
    			else if(c!=null)
    			{
    				String temp = null;
    				temp = c;
    				c = null;
    				notify();
    				System.out.println("Got: " + temp);
    				return temp;
    			}
    			else if(b!=null)
    			{
    				String temp = null;
    				temp = b;
    				b = null;
    				notify();
    				System.out.println("Got: " + temp);
    				return temp;
    			}
    			else if(a!=null)
    			{
    				String temp = null;
    				temp = a;
    				a = null;
    				notify();
    				System.out.println("Got: " + temp);
    				return temp;
    			}
    			else
    			{
    				return null;
    			}
    	}
    	synchronized void put(String n) {
    		if(a!=null && b!=null && c!=null && d!=null)
    			try {
    				wait();
    			} catch(InterruptedException e) {
    				System.out.println("InterruptedException caught");
    			}
     
    			if(d==null || c==null || b==null || a==null)
    			{
    				d = c;
    				c = b;
    				b = a;
    				a = n;
    			}
    			System.out.println("Put: " + n);
    			notify();
    	}
    }
    Producteur et consommateur:
    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
     
    class Producer implements Runnable {
    	Q q;
     
    	public String processedString = "";
     
    	private String getNextCharacter() {
     
    		String temp = processedString;
     
    		String cs = null;
     
    		if(temp!=null)
    		{
    			try {
    			cs = temp.substring(0,1);
    			processedString = temp.substring(1, temp.length());
    			} catch(Exception e) {
    				return null;
    			}
    		}
     
    		return cs;
    	}	
     
    	Producer(Q q, String s) {
    		this.processedString = s;
    		this.q = q;
    		new Thread(this, "Producer"+s).start();
    	}
    	public void run() {
    		while(true) {
    			String character = this.getNextCharacter();
    			if(character!=null)
    				q.put(character);
    		}
    	}
    }
     
    class Consumer implements Runnable {
    	Q q;
    	Consumer(Q q) {
    		this.q = q;
    		new Thread(this, "Consumer").start();
    	}
    	public void run() {
    		while(true) {
    			q.get();
    		}
    	}
    }
    Main:
    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
     
    class PCFixed {
    	public static void main(String args[]) {
    		Q q = new Q();
    		new Producer(q,"IVEHEARDTHEREWASASECRETCHORD");
    		//new Producer(q, "XYXYXYXYXYXYXYXYXYX");
    		new Consumer(q);
    		//new Consumer(q);
    		System.out.println("Press Control-C to stop.");
    	}
    }
     
    class Test
    {
    	public static void main(String args[])
    	{
    		PCFixed p = new PCFixed();
    		p.main(args);
    	}
    }
    Toute aide est grandement appréciée , je vais aussi chercher de mon coté cet après midi.

  2. #2
    Membre averti
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    338
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2008
    Messages : 338
    Points : 402
    Points
    402
    Par défaut
    Utilise au lieu de tes varibles a, c.. dans la classe Q une LinkedList<Character>.
    -Qd tu fais un put(char c) tu fait un addFirst() si la taille de la list < 5 sinon wait() jusqu'à notification.
    -Qd tu fais un get() tu fais un removeLast() si la taille > 0 sinon un wait() jusqu'à notification.
    NB: faire bien attention à la synchronisation de tes threads (bloc synchronized(taListe)) lors d'opérations atomiques..
    A++

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    13
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 13
    Points : 12
    Points
    12
    Par défaut
    Merci Hibour pour ta réponse qui a réduit la complexité et amélioré la lisibilité de mon code.

    Voici la dernière version de la classe Q:

    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
     
    class Q {
    	LinkedList<String> buffer = new LinkedList<String>();
     
    	synchronized String get() {
    		if(buffer.size()==0)
    		{
    			try {
    				wait();
    			} catch(InterruptedException e) {
    				System.out.println("InterruptedException caught");
    			}
    		}
     
    		System.out.println("Got: " + buffer.getLast());
    		notify();
    		return buffer.removeLast();
    	}
    	synchronized void put(String n) {
    		if(buffer.size()>3)
    		{
    			try {
    				wait();
    			} catch(InterruptedException e) {
    				System.out.println("InterruptedException caught");
    			}
    		}		
    		buffer.addFirst(n);
    		System.out.println("Put: " + n);
    		notify();
    	}
    }
    Et l'output lorsque j'ai un producteur et un consommateur:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    Press Control-C to stop.
    Put: I
    Put: V
    Put: E
    Put: H
    Got: I
    Put: E
    Got: V
    Put: A
    Got: E
    Put: R
    Got: H
    ...
    Et l'output lorsque j'ai deux producteurs (c'est là que cela pose problème):
    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
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
     
    Press Control-C to stop.
    Put: I
    Put: V
    Put: E
    Put: H
    Got: I
    Put: E
    Put: X
    Put: A
    Put: Y
    Put: R
    Put: X
    Put: D
    Put: Y
    Got: V
    Got: E
    Got: H
    Got: E
    Got: X
    Got: A
    Got: Y
    Got: R
    Got: X
    Got: D
    Got: Y
    Put: T
    Got: T
    Put: H
    Put: E
    Put: R
    Put: E
    Put: X
    Put: W
    Got: H
    Got: E
    Got: R
    Got: E
    Got: X
    Got: W
    Put: A
    Put: S
    Put: A
    Put: S
    Got: A
    Got: S
    Got: A
    Got: S
    Put: E
    Put: C
    Put: R
    Put: E
    Got: E
    Got: C
    Got: R
    Got: E
    Put: T
    Put: C
    Put: H
    Put: O
    Got: T
    Put: R
    Put: Y
    Put: D
    Put: X
    Got: C
    Got: H
    Got: O
    Got: R
    Got: Y
    Got: D
    Got: X
    Put: Y
    Put: X
    Put: Y
    Put: X
    Got: Y
    Got: X
    Got: Y
    Got: X
    Put: Y
    Put: X
    Put: Y
    Put: X
    Got: Y
    Got: X
    Got: Y
    Got: X
    Put: Y
    Got: Y
    Put: X
    Got: X
    Put: Y
    Put: X
    Got: Y
    Got: X
    -> Il y a + de 4 puts qui se suivent après le premier got, alors que je devrai avoir un équilibre, enfin je veux dire un buffer qui ne dépasse jamais les 4 éléments.

  4. #4
    Membre à l'essai
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    13
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 13
    Points : 12
    Points
    12
    Par défaut
    Je pense que mon problème vient du fait que si deux producteurs arrivent au même moment à la ligne du test:

    if(buffer.size()>3)
    Dans ce cas aucun des deux ne va wait(), donc ils vont tous les deux ajouter un élément. J'ai détécté ce problème en essayant avec 2 consommateurs, cela a déclenché une exception lors de la suppression d'un élément de la liste car j'essaye de supprimer un élément alors qu'il n'y en avait plus.

    Je vais essayer de trouver une solution pour empecher deux producteurs ou deux consommateurs à passer le test.

    EDIT: Bah si mes méthodes sont synchronized comment se fait-il que deux producteurs et deux consommateurs puissent entrer dans les méthodes?

  5. #5
    Membre à l'essai
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    13
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 13
    Points : 12
    Points
    12
    Par défaut
    Problème résolu en ayant rajouté un test après le premier wait(); des méthodes get et put:

    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
     
    class Q {
    	LinkedList<String> buffer = new LinkedList<String>();
     
    	synchronized void get() {
    		if(buffer.size()==0)
    		{
    			try {
    				wait();
    			} catch(InterruptedException e) {
    				System.out.println("InterruptedException caught");
    			}
    		}
    		try {
    			System.out.println("Got: " + buffer.getLast());
    			buffer.removeLast();
    		} catch (NoSuchElementException e)
    		{
    			try {
    				wait();
    			} catch(InterruptedException f) {
    				System.out.println("InterruptedException caught");
    			}
    		}
    		notify();
    	}
    	synchronized void put(String n) {
    		if(buffer.size()>3)
    		{
    			try {
    				wait();
    			} catch(InterruptedException e) {
    				System.out.println("InterruptedException caught");
    			}
    		}		
    		if(buffer.size()<4)
    		{
    			buffer.addFirst(n);
    			System.out.println("Put: " + n);
    		}
    		else
    		{
    			try {
    				wait();
    			} catch(InterruptedException e) {
    				System.out.println("InterruptedException caught");
    			}			
    		}
    		notify();
    	}
    }
    Pour être honnête je pense avoir été chanceux d'avoir trouvé comment résoudre ce problème, je ne vois pas sémantiquement où est-ce que je me suis trompé ou bien ce qui faisait que cela ne fonctionnait pas.

    Je peux avoir maintenant N producteurs et M consommateurs sans problèmes.

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

Discussions similaires

  1. Réponses: 13
    Dernier message: 11/06/2015, 15h51
  2. Problème de synchronisation entre Thread et VCL
    Par Jipété dans le forum Débuter
    Réponses: 33
    Dernier message: 21/05/2012, 11h14
  3. Evenement et thread : problème de synchronisation ?
    Par Ricavir dans le forum Windows Forms
    Réponses: 9
    Dernier message: 15/04/2009, 07h31
  4. problème de synchronisation de thread
    Par youp_db dans le forum Entrée/Sortie
    Réponses: 2
    Dernier message: 11/10/2006, 11h34
  5. Problème de synchronisation dans un JTextArea
    Par wutang dans le forum Composants
    Réponses: 3
    Dernier message: 21/06/2004, 15h06

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