2017-02-15 6 views
1

Der Code geht in den Deadlock. Selbst wenn es zum Producer-Teil geht, sobald es wait() erreicht, geht es in Deadlock. Aus meiner Sicht, wenn wait() getroffen wird, sollte es zu Consumer-Thread gehen, anstatt in Deadlock zu gehen.Mein Producer Consumer-Code wird in Deadlock gehen

package com.java.thread.self.practice; 

public class Producer_Consumer { 

     private volatile boolean prodFlag = true; 
     private volatile boolean consFlag = false; 

     public static void main(String[] args){ 

      Producer_Consumer producer_Consumer = new Producer_Consumer(); 
      producer_Consumer.startThreads(); 

     } 

     private void startThreads() { 

      Thread producer = new Thread(new Runnable(){ 

       @Override 
       public void run() { 
        while(true){ 
         try { 
          System.out.println("Before Producer invocation :::::: "); 
          producer(); 
          Thread.sleep(100); 
         } catch (InterruptedException e) { 
          // TODO Auto-generated catch block 
          e.printStackTrace(); 
         } 
        } 

       } 

      }); 



      Thread consumer = new Thread(new Runnable(){ 

       @Override 
       public void run() { 
        while(true){ 
         try { 
          System.out.println("Before Consumer invocation :::::: "); 
          consumer(); 
          Thread.sleep(100); 
         } catch (InterruptedException e) { 
          // TODO Auto-generated catch block 
          e.printStackTrace(); 
         } 
        } 
       } 

      }); 


      producer.start(); 
      consumer.start(); 
     } 

     void producer() throws InterruptedException { 

      System.out.println("Inside the producer method ::::: "+this.getClass()); 

      synchronized(this){ 

       if(prodFlag){ 

        System.out.println("PRODUCE !!!"); 
        consFlag = true; 
        System.out.println("Before calling wait in producer :::::: "); 
        notify(); 
        wait(); 
        System.out.println("After calling wait in producer :::::: "); 

       }else{ 

        System.out.println("Before calling notify in producer :::::: "); 
        consFlag = true; 
        wait(); 
        System.out.println("After calling notify in producer :::::: "); 

       } 


      } 
     } 

     void consumer() throws InterruptedException { 

      System.out.println("Inside the consumer method ::::: "+this.getClass()); 

      synchronized(this){ 

       if(consFlag){ 

        System.out.println("CONSUME !!!"); 
        prodFlag = true; 
        System.out.println("Before calling wait in consumer :::::: "); 
        notify(); 
        wait(); 
        System.out.println("After calling wait in consumer :::::: "); 

       }else{ 

        System.out.println("Before calling notify in consumer :::::: "); 
        prodFlag = true; 

        wait(); 

        System.out.println("After calling wait in consumer :::::: "); 

       } 

      } 
     } 
} 
+0

Ich habe Ihren Code getestet und es blockiert nicht. Er druckt kontinuierlich "Produce" "Consume" in der Konsole – Flood2d

+0

Versuchen Sie im Debug-Modus. –

+1

Was passiert, wenn sowohl Ihr Producer-Thread als auch Ihr Consumer-Thread 'notify()' aufrufen und dann beide 'wait()' aufrufen? Was dachtest du, würdest du einen von ihnen wieder aufwecken? –

Antwort

2

Wenn Sie das tun

synchronized(this) 

Sie die ganze Klasse sperren. Und es wird bis zum Ende dieses Codeblocks gesperrt sein. Da Sie Ihre Flags volatile deklarieren, sollte keine explizite Synchronisation erforderlich sein. In diesem Fall müssen Sie wait() und notify überhaupt nicht signalisieren. Wenn Sie jedoch eine atomare Geschäftslogik haben möchten, müssen Sie Ihren Code überarbeiten, um nicht den gesamten großen Block mit Ihrer Klasse als Schlüssel zu blockieren.

+0

zu aktualisieren "hier sollte keine explizite Synchronisation erforderlich sein." Abgesehen von der Tatsache [Sie müssen den Monitor halten, um zu warten und zu benachrichtigen] (https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#wait()). –

+0

Danke für Ihre Eingabe. Obwohl ich versuchte, mit flüchtigen Schlüsselwort zu entfernen, geht es immer noch in Deadlock. Meine Frage ist, wenn es wait() trifft, sollte es zum Verbraucherthread gehen, anstatt zum Deadlock zu gehen. –

+0

Meine Frage ist, warum es nicht zum Verbraucherblock geht, sobald es den wait() im Produzentenblock trifft. –

1

Ihr Programm geht nicht in den Deadlock - weder beim Ausführen noch beim Debugging. Ich nehme an, Sie sind nicht mit dem Debuggen von mehr als einem Thread vertraut, richtig? Vielleicht scheint es Ihnen, dass Ihr produzierender Thread in einem Deadlock ist, während Sie zum konsumierenden Thread wechseln und das Debuggen fortsetzen müssen?