共享对象

时间:2016-09-03 12:36:47

标签: multithreading

我正在尝试创建单变量生产者消费者解决方案,但我在Producer的notifyAll()方法中得到了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)

1 个答案:

答案 0 :(得分:2)

这是问题所在:

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

了解您不在变量上进行同步非常重要 - 您在对象上进行同步。因此,您要修改x的值以引用不同的Integer对象,然后在那个不同的对象上调用notifyAll ...拥有该对象的监视器。

我强烈建议您不要使用Integer个对象进行同步。理想情况下,使用一个不用于任何其他目的的对象 - 这样可以更容易推理。

你仍然可以拥有你的x变量,并记录除了线程持有适当的锁之外不应该修改它 - 但是让它独立于锁本身。