class order
{
private static int i=0;
private int count=(++i);
public order()
{
if(count==10)
{System.out.println("order==10");System.exit(0);} 
}
public String toString()
{
return "order:"+count;
}
}
class middle
{
private order or;
public synchronized void  setOrder(order o)
{
this.or=o;
}
public synchronized order gerOrder()
{
return or;
}
}
class productor extends Thread
{
private middle mi;
public productor(middle m)
{
mi=m;
start();
}
public synchronized void run()
{
while(true)
{
         while(mi.gerOrder()!=null)
{
try{System.out.println("wait consumer "+mi.gerOrder());wait();}

catch(InterruptedException e)
{
throw new RuntimeException(e);
}
}
if(mi.gerOrder()==null)
{
mi.setOrder(new order()); 
System.out.println("purducted");
notifyAll();
                           }
}
}
}
class consumer extends Thread
{
private middle mi;
public consumer(middle m)
{
mi=m;
start();
}
public synchronized void run()
{
while(true)
{

while(mi.gerOrder()==null)
{
try{System.out.println("wait productor");wait();}
catch(InterruptedException e){throw new RuntimeException(e);}
}


if(mi.gerOrder()!=null)
{
System.out.println("consumed "+mi.gerOrder());
mi.setOrder(null);
notifyAll();
}


}
}
}
public class productor_and_consumer
{
public static void main(String[] args)
{
middle mid=new middle();
productor p=new productor(mid);
consumer c=new consumer(mid);
}
}输出为:purducted
wait consumer order:1
consumed order:1
wait productor
然后就死锁了,我把run方法都同步了,还是会死锁,请各位高手帮我分析一下,为什么会死锁,万分感谢!

解决方案 »

  1.   

    我想楼主可能理解错了,在你的程序中你productor p=new productor(mid);
    consumer c=new consumer(mid);
    这样声明的是两个线程类的实例,每个线程实例都拥有自己的run方法,所以你将run方法同步和同步没多大关系,你现在是在两个线程中共享一个资源也即是mid这个对象,所以你应该对这个mid对象同步,使两个线程轮流获得这个对象的锁!用完后释放这个锁,防止出现死锁!
    而不是同步run方法!
      

  2.   

    你共享的是mid这个引用,只要把让这个变量通过sync段就可以了,同步run方法目标太大,容易出现意想不到的bug
      

  3.   

    我目的是模拟生产者消费者问题,根据楼上几位大哥所说,共享的是mid这个引用,只要把让这个变量通过sync段就可以了,但我已经把middle类的get和set方法同步了,为什么还会死锁呢?
      

  4.   

    只要把get和set方法同步就可以了
      

  5.   

    一个对象中的所有synchronized方法都共享一把锁,这把锁能够防止多个方法对通用
    内存同时进行的写操作。
      

  6.   

    这程序造成死锁的关键是wait();
      

  7.   

    我现在知道如何会导致死锁,比如:当productor类已经生产了个ORDER,当他运行到System.out.println("wait consumer "+mi.gerOrder())时,由于某种原因被中断,然后consumer占有CPU,然后运行了System.out.println("consumed "+mi.gerOrder());
    mi.setOrder(null);
    notifyAll();
    这段代码,(注意:这时productor的wait()方法还没被执行到),随后刚才被中断的productor占有CPU,执行wait(),而此时mi.gerOrder()==null,所以consumer也会等待,这样引起死锁.我现在想的是当执行到关键段时,如productor的
    while(mi.gerOrder()!=null)
    {
    try{System.out.println("wait consumer "+mi.gerOrder());wait();}

    catch(InterruptedException e)
    {
    throw new RuntimeException(e);
    }
    }
    时不能被中断或即使可以被中断,consumer也不能被执行.请问各位高手有什么方法?
    万分感谢!
      

  8.   

    楼上:如过把wait();换成sleep();那怎么唤醒呢?
      

  9.   

    不需要唤醒,你设置一个睡眠时间:
    sleep(1000)象这样让时间过后自动回复!
      

  10.   

    在run方法中一个安全的位置试用suspendRequested变量,你的consumer线程发现
    变量设置好了就进入等待状态,知道变量可以用为止举个例子
    class SuspendRequestor

        private boolean  suspendRequested;
        public synchronized void set (boolean b)
        {
            suspendRequested = b;
            notifyAll();
        }
        public synchronized void waitForResume( )
                throws InterruptedException
        {
              while(suspendRequested) wait();
         }
    }   应用程序:
          class MyThread extends Thread
         {
           public void requestSuspend( )
            {
              suspender.set(true);
             }
           public void requestResume( )
           {
              suspender.set(false);
            }
            public void run( )
            {
               try
               {
                 while (.....)
                  {
                     suspender.waitForResume();
                         ......
                  }
      

  11.   

    或者用wait(long millis) 带超时参数的等待