2010-12-14 3 views
0

J'ai écrit du code pour implémenter le problème producteur-consommateur et il semble fonctionner correctement sans avoir besoin de synchroniser.Est-ce possible?producteur-consommateur utilisant la synchronisation

Comment tester le code et vérifier s'il fonctionne correctement ou non? Comment savoir si un blocage se produira? Pour l'instant, je ne suis pas en train de sortir des boucles (c'est-à-dire que le producteur continue à insérer et le consommateur continue à consommer dans une boucle infinie) .J'utilise une file circulaire de taille 3 (par souci de simplicité) comme ressource partagée.

Voici mon code:

import java.util.*; 

public class PCImpl implements Runnable 
{ 
Thread t; 
QforPC qObj; 

public static void main(String[] args) 
{ 
    QforPC qObject=new QforPC(); 

    //These create 2 different objects! Each object has it's own thread of execution. 
    //Synchronization is needed when 2 threads use the same object 
    new PCImpl("Producer",qObject); 
    new PCImpl("Consumer",qObject); 
} 

PCImpl(String name,QforPC qObj) 
{ 
    this.qObj=qObj; 
    t=new Thread(this,name); 
    t.start(); 
} 

public void run() 
{ 
     if(Thread.currentThread().getName().equals("Producer")) 
     { 
      while(true) 
      { 
        Random rgen=new Random(); 
        int n=rgen.nextInt(100); 
        if(n!=0) 
           qObj.Producer(n); 
         try 
        { 
         Thread.sleep(200); 
        } 
         catch(InterruptedException e) 
        { 

        } 
       } 

      } 


     if(Thread.currentThread().getName().equals("Consumer")) 
     { 
      while(true) 
        { 
       try 
       { 
       Thread.sleep(1500); 
       } 
       catch(InterruptedException e) 
       { 
        } 
       qObj.Consumer(); 

       } 
     } 

    } 
} 



public class QforPC 
{ 
int[] q={0,0,0}; 
int r=0,f=0; 
    public void Producer(int item) 
    { 

     if(r!=q.length && canProducer()) 
     { 
      q[r]=item; 
      System.out.println("The item inserted into the queue is:"+ item); 
      r++; 
     } 
     if(r==q.length && f>0) 
      r=0; 
     else if(r==q.length && f==q.length) 
     { 
      r=0; 
      f=0; 
     } 
    } 

    public void Consumer() 
    { 
     int item; 
     System.out.println("The value of isQueue empty is:"+ isEmpty()); 

     if(f!=q.length && isEmpty()==false) 
     { 
      System.out.println("Entered the consumer method"); 
      item=q[f]; 
      System.out.println("The item fetched from the queue is:"+item); 
      q[f]=0; 
      f++; 
     } 
     if(f==q.length && r<f) 
      f=0; 

    } 

    public boolean isEmpty() 
    { 
     for(int k=0;k<q.length;k++) 
     { 
      if(q[k]==0 && k==q.length-1) 
       return true; 

     } 
     return false; 
    } 

    public boolean canProducer() 
    { 
     for(int k=0;k<q.length;k++) 
     { 
       if(q[k]==0) 
       return true; 

     } 
     return false; 
    } 
} 
+1

Il sera probablement gâcher si vous supprimez le 'Sleeps'. – SwDevMan81

+2

Bienvenue à la nature des bugs de synchronisation. Cela semble fonctionner correctement jusqu'au moment où il explose complètement. –

+2

Pourquoi ne pas séparer la logique du producteur et du consommateur en deux implémentations séparées de «Runnable»? Cette conception est très inéligante et conduira à un code complètement non-identifiable. –

Répondre

1

Ce que vous avez essayé de faire est d'implémenter la synchronisation en utilisant busy-waiting. Dans le code de pseudo ce que vous faites est essentiellement:

Producer() 
{ 
    if (buffer.hasemptyspaces()) 
    { 
     produce(buffer); 
    } 
    else 
    { 
     sleep(n); 
    } 
} 

Consumer() 
{ 
    if (buffer.hasfullspaces()) 
    { 
     consume(buffer); 
    } 
    else 
    { 
     sleep(n); 
    } 
} 

code Vous fonctionnera bien, jusqu'à ce que le producteur et le consommateur essayer simultanément d'exécuter des produits() et de consommer(). En d'autres termes, l'un ou l'autre de Cela peut ne pas être très souvent, mais est certainement possible et arrivera certainement!

En Java, ConcurrentLinkedQueue implémente un algorithme sans attente pour un tampon partagé. Je suis sûr que ce sont d'autres implémentations si vous regardez autour.

+0

Donc, cela signifie qu'il ne peut pas fonctionner sans synchronisation dans ma mise en œuvre et à un moment donné le programme va planter? – collegian

+1

Oui. Lors de la mise en œuvre de threads et de données partagées, il est utile de penser "S'il existe un moyen d'entrelacer vos threads de telle sorte qu'ils se bloquent, le planificateur le trouvera". –

0

Il n'y a pas une telle chose comme the Producer-Consumer problem. Le producteur-consommateur est un modèle de conception qui peut ou non être une mise en œuvre efficace d'une solution à un problème, et non un problème en soi.

Je suis sûr qu'il y a beaucoup d'implémentations producteur-consommateur qui ne nécessitent pas de synchronisation. Cela dépend entièrement de ce que vous essayez d'accomplir et du type de données que vous produisez ou consommez.

De plus, vous devez avoir un problème à résoudre si vous voulez dire que votre implémentation fonctionne sans synchronisation. Travaille à faire quoi? Je n'ai aucune idée de ce que tu fais.

+0

Je suis juste en train de produire et de consommer! – collegian

+0

Drôle, l'article de Wikipédia sur le «problème du producteur-consommateur» semble être en désaccord. –

+0

On dirait que ma définition du problème n'est pas la même que la leur. Je suppose que c'est pourquoi je suis un ingénieur et pas un informaticien. – Falmarri

0

Cela peut être fait avec une file d'attente sans verrou, mais pas comme ça, je vous recommande de lire Java Concurrency in Practice. Si votre code est accédé par plusieurs threads en même temps, vous aurez beaucoup d'erreurs à ce sujet, vous avez des problèmes de publication et de synchronisation! Mais comme Farlmarri a déclaré que cela dépend de l'utilisation de ce code.

0

Votre code fonctionne à cause du timing et du fait que si l'un des deux threads échoue à mettre/récupérer la ressource il le demande dort essentiellement pendant un certain temps et essaie à nouveau. Bien que cette détérioration (lorsque vous n'avez pas à gérer immédiatement un événement), il perd du temps CPU.

C'est pourquoi sémaphores sont fortement suggéré d'aborder ce genre de question que vous pouvez lire ici

http://en.wikipedia.org/wiki/Producer-consumer_problem

bye

+0

En fait, il semble que l'implémentation de l'OP soit assez similaire à l'implémentation listée dans cet article comme "inadéquate". –