2016-09-03 2 views
0

Я пытаюсь создать однопользовательское потребительское решение переменной, но я получаю IllegalMonitorStateException в методе notducAll() производителя Producer. Я также приобретаю блокировку в синхронизированном блоке, что могло бы пойти не так?IllegalMonitorStateException при совместном использовании объекта

/** 
* Write a description of class SingleProducerConsumer here. 
* 
* @author (your name) 
* @version (a version number or a date) 
*/ 
public class SingleProdCons 
{ 

    public static void main(String args[]) 
    { 
     Integer x = 0; 
     Thread producer = new Thread(new Producer(x),"Producer"); 
     Thread consumer = new Thread(new Consumer(x),"Consumer"); 
     producer.start(); 
     consumer.start(); 
    }  
} 

    class Producer implements Runnable 
    { 
     private Integer x; 

     Producer(Integer x) 
     { 
      this.x = x; 
     } 

     @Override 
     public void run() 
     { 
      synchronized(x) 
      { 
      while(x.equals(0)==false){ 

       //The value of the variable has not been consumed yet , we should wait here till it gets consumed 
       try{ 
       x.wait(); 
       }catch(InterruptedException ie) 
       { 
        System.out.println("Caught Exception : "+ie.getMessage()); 
       } 

      } 

      //Else initialze the variable and let it get used by the Consumer then 
      synchronized(x) 
      { 
       x=10; 
       x.notifyAll(); 

      } 
     } 

     } 

    } 

    class Consumer implements Runnable 
    { 
     private Integer x; 

     Consumer(Integer x) 
     { 
      this.x = x; 
     } 

     @Override 
     public void run() 
     { 
      synchronized(x) 
      { 
      while(x.equals(0)==true) 
      { 
       //The value has not been put by the Producer thread yet hence we should wait here 
       System.out.println("We are before the method call of the wait on the x object"); 
       try{ 
       x.wait(); 
       }catch(InterruptedException ie) 
       { 
        System.out.println("Caught the exception : "+ie.getMessage()); 
       } 
      } 
      } 

      synchronized(x) 
      { 
       System.out.println("Consuming : "+x); 
       x.notifyAll(); 
      } 

     } 

    } 

Exception in thread "Producer" java.lang.IllegalMonitorStateException 
    at java.lang.Object.notifyAll(Native Method) 
    at Producer.run(SingleProdCons.java:55) 
    at java.lang.Thread.run(Thread.java:745) 
Exception in thread "Producer" java.lang.IllegalMonitorStateException 
    at java.lang.Object.notifyAll(Native Method) 
    at Producer.run(SingleProdCons.java:55) 
    at java.lang.Thread.run(Thread.java:745) 
Exception in thread "Producer" java.lang.IllegalMonitorStateException 
    at java.lang.Object.notifyAll(Native Method) 
    at Producer.run(SingleProdCons.java:55) 
    at java.lang.Thread.run(Thread.java:745) 
Exception in thread "Producer" java.lang.IllegalMonitorStateException 
    at java.lang.Object.notifyAll(Native Method) 
    at Producer.run(SingleProdCons.java:55) 
    at java.lang.Thread.run(Thread.java:745) 

ответ

2

Это проблема:

synchronized(x) 
{ 
    x=10; 
    x.notifyAll(); 
} 

Важно понимать, что вы не синхронизируются на переменной - синхронизации на объекта. Таким образом, вы изменяете значение x, чтобы обратиться к другому объекту Integer, и затем вы вызываете notifyAll на этот другой объект ... из потока, который не является владельцем монитора для этого объекта.

Я настоятельно рекомендую вам не использовать Integer объекты для синхронизации вообще. В идеале используйте объект, который не используется для любой другой цели, что упрощает рассуждение.

У вас все еще есть переменная x и документ, который он не должен изменять, кроме тех случаев, когда нить содержит соответствующую блокировку, но делает ее независимой от самой блокировки.

+0

Ну, это звучит круто, но что вы имеете в виду, если не использовать для каких-либо других целей. Если я использую private final Vector sharedQueue, он работает хорошо. :) – Chetan

+0

@Chetan: Я имею в виду, что вы используете его только для целей синхронизации/ожидания/уведомления ... что означает, что вы можете иметь один объект, даже если значения, которые он «защищает», изменяются. Я бы настоятельно советовал * против * использовать «Вектор», например, потому что операции с «Вектор» сами синхронизированы, вставляя все, что вы делаете. Как только вы начнете беспокоиться о том, что другой код собирается получать/выпускать (и, возможно, уведомлять/ждать) на мониторе, сложнее рассуждать о вашем коде. –

+0

Вы хотите использовать другую переменную для модификации, а для задачи wait/notify будет отличаться varaible? – Chetan

Смежные вопросы