2017-02-15 145 views
1

代碼進入死鎖。即使它一出現wait()即將生產者部分,它就陷入僵局。從我的理解,如果wait()被擊中,它應該去消費者線程,而不是進入死鎖。我的生產者消費者代碼進入死鎖

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

我測試了你的代碼,它沒有死鎖。他連續打印控制檯中的「生產」「消費」 – Flood2d

+0

嘗試調試模式。 –

+1

如果生產者線程和消費者線程調用'notify()',然後他們都調用'wait()',會發生什麼?你在想什麼會喚醒他們其中一個呢? –

回答

2

當你做到這一點

synchronized(this) 

你鎖定全班。它將被鎖定,直到該代碼塊結束。既然你聲明你的標誌volatile應該不需要顯式同步。

在這種情況下,您根本不需要發出wait()notify的信號。但是,如果你想擁有一些原子商業邏輯,你需要重新修改你的代碼,不要把你的類作爲關鍵塊阻塞整個大塊。

+0

「這裏不應該是需要顯式同步的。」除了這個事實[你必須讓監視器調用wait和notify](https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#wait())。 –

+0

感謝您的輸入。 即使我嘗試使用易失性關鍵字進行刪除,它仍會陷入僵局。我的問題是,如果它等待(),它應該去消費者線程,而不是去死鎖。 –

+0

我的問題是爲什麼它不會消費塊,一旦它碰到生產者塊中的wait()。 –

1

程序不會進入死鎖狀態 - 無論是在運行時還是在調試時。我想你不熟悉調試多個線程,對吧?也許在你看來,當你不得不切換到消費線程並繼續調試時,你的生產線程處於死鎖狀態?