黑马程序员技术交流社区

标题: 求解决一个问题 [打印本页]

作者: Ezreal    时间: 2014-8-2 23:48
标题: 求解决一个问题
谁能帮我看下下面的异常是什么意思,谢谢了
Exception in thread "Thread-1" java.lang.Error: Maximum lock count exceeded
        at java.util.concurrent.locks.ReentrantLock$Sync.nonfairTryAcquire(ReentrantLock.java:141)
        at java.util.concurrent.locks.ReentrantLock$NonfairSync.tryAcquire(ReentrantLock.java:213)
        at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1198)
        at java.util.concurrent.locks.ReentrantLock$NonfairSync.lock(ReentrantLock.java:209)
        at java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:285)
        at cn.program.thread.Goods.set(Producer.java:30)
        at cn.program.thread.Producer.run(Producer.java:96)
        at java.lang.Thread.run(Thread.java:745)

作者: fantacyleo    时间: 2014-8-2 23:50
锁计数太多了,你这是递归过多还是死循环了?
作者: Ezreal    时间: 2014-8-2 23:58
fantacyleo 发表于 2014-8-2 23:50
锁计数太多了,你这是递归过多还是死循环了?
  1. 这是源码,大神帮忙看一下
  2. import java.util.concurrent.locks.Condition;
  3. import java.util.concurrent.locks.Lock;
  4. import java.util.concurrent.locks.ReentrantLock;


  5. class Goods{
  6.          private String name;
  7.          private int num = 1;
  8.          private boolean flag = false;
  9.          private Lock lock = new ReentrantLock();
  10.          private Condition condition_pro = lock.newCondition();
  11.          private Condition condition_con = lock.newCondition();       
  12.          
  13.          public void set(String name) throws InterruptedException
  14.          {
  15.                  lock.lock();
  16.                  while(flag)
  17.                          try
  18.                  {
  19.                      condition_pro.await();
  20.                          this.name  = name+"..."+num++;
  21.                      System.out.println(Thread.currentThread().getName()+"---生产者"+this.name);
  22.                      flag = true;
  23.                      condition_con.signal();
  24.                  }
  25.                      finally
  26.                      {
  27.                              lock.unlock();
  28.                      }
  29.                  
  30.          }
  31.        
  32.          public void out() throws InterruptedException
  33.          {
  34.                  lock.lock();
  35.                  while(!flag)
  36.                          try
  37.                  {
  38.                                  condition_con.await();
  39.                                  System.out.println(Thread.currentThread().getName()+"------消费者"+this.name);
  40.                                  flag = false;
  41.                                  condition_pro.signal();

  42.                  }
  43.                  finally
  44.                  {
  45.                           lock.unlock();
  46.                  }
  47.                
  48.                
  49.          }
  50. }
  51. class Producer implements Runnable {
  52.          private Goods g;
  53.          Producer(Goods g)
  54.          {
  55.                 this.g = g;
  56.          }
  57.          public void run()
  58.          {
  59.                 while(true)
  60.                 {
  61.                         try
  62.                         {
  63.                                 g.set("+商品+");
  64.                         }
  65.                         catch(InterruptedException e){}
  66.                 }
  67.          }
  68. }
  69. class Consumer implements Runnable{
  70.          private Goods g;
  71.         Consumer(Goods g)
  72.          {
  73.                 this.g = g;
  74.          }
  75.         public void run()
  76.         {
  77.                 while(true)
  78.                 {
  79.                         try
  80.                         {
  81.                                 g.out();
  82.                         }
  83.                         catch(InterruptedException e){}
  84.                 }
  85.         }
  86. }
  87. public class ProducerConsumerDemo {
  88.         public static void main(String[] args)
  89.         {
  90.                 Goods g = new Goods();
  91.                 //new Thread(new Producer(g)).start();
  92.                 //new Thread(new Consumer(g)).start();
  93.                 Producer pro = new Producer(g);
  94.                 Consumer con = new Consumer(g);
  95.                 Thread t1 = new Thread(pro);
  96.                 Thread t2 = new Thread(pro);
  97.                 Thread t3 = new Thread(con);
  98.                 Thread t4 = new Thread(con);
  99.                 t1.start();
  100.                 t2.start();
  101.                 t3.start();
  102.                 t4.start();
  103.         }

  104. }
复制代码

作者: s_gd    时间: 2014-8-3 00:12
表示看不懂的路过
作者: fantacyleo    时间: 2014-8-3 00:22
Ezreal 发表于 2014-8-2 23:58

明白了,set和out方法中的while条件设置出了问题。比如set方法中你while(flag),结果生产完了flag又设为true,那不就死循环了?
作者: Ezreal    时间: 2014-8-3 00:37
fantacyleo 发表于 2014-8-3 00:22
明白了,set和out方法中的while条件设置出了问题。比如set方法中你while(flag),结果生产完了flag又设为t ...

set方法中while为true是进入等待,为false就生产,生产完成设置为true就不再生产,唤醒消费者进行消费。这样没错吧。。
作者: fantacyleo    时间: 2014-8-3 00:47
Ezreal 发表于 2014-8-3 00:37
set方法中while为true是进入等待,为false就生产,生产完成设置为true就不再生产,唤醒消费者进行消费。 ...

可你的while循环把生产也包括进来了,如果flag=flase,那么while循环根本就不执行,什么都不生产,
作者: fantacyleo    时间: 2014-8-3 00:54
Ezreal 发表于 2014-8-3 00:37
set方法中while为true是进入等待,为false就生产,生产完成设置为true就不再生产,唤醒消费者进行消费。 ...

你的程序现在的执行逻辑是这样的:

一开始flag为false,消费者进out,上锁,判断while为真,进入循环,然后马上等待,释放锁。接着生产者进set,上锁,判断while为假,不执行,而且由于没有进入try/catch,finally也不会执行,锁没释放,也没唤醒消费者。由于run方法设置了while(true),于是又回来set拿一次锁,锁计数+1,判断while为假,不执行,而且由于没有进入try/catch,finally也不会执行,锁没释放,也没唤醒消费者。由于run方法设置了while(true),于是又回来set拿一次锁,锁计数+1。。。最后就是锁计数溢出
作者: fantacyleo    时间: 2014-8-3 01:01
把get和set方法改成这样就好了。lock上锁之后的语句要立刻用try/finally包围起来,这样才能保证锁一定会被释放
  1. public void set(String name) throws InterruptedException
  2.          {
  3.                  lock.lock();
  4.                  try {
  5.                  while(flag)
  6.                      condition_pro.await();

  7.                  this.name  = name+"..."+num++;
  8.                  System.out.println(Thread.currentThread().getName()+"---生产者"+this.name);
  9.                  flag = true;
  10.                  condition_con.signal();
  11.                  }
  12.                  finally
  13.                  {
  14.                          lock.unlock();
  15.                  }

  16.          }
  17.         
  18.          public void out() throws InterruptedException
  19.          {
  20.                  lock.lock();
  21.                  try {
  22.                          while(!flag)
  23.                                  condition_con.await();
  24.                          System.out.println(Thread.currentThread().getName()+"------消费者"+this.name);
  25.                          flag = false;
  26.                          condition_pro.signal();

  27.                  }
  28.                  finally
  29.                  {
  30.                          lock.unlock();
  31.                  }
  32.                
  33.                
  34.          }
复制代码

作者: niushicha    时间: 2014-8-3 01:31
看起有点晕哦!
作者: Joemi    时间: 2014-8-3 08:19
路过,帮顶~
作者: Ezreal    时间: 2014-8-3 09:05
fantacyleo 发表于 2014-8-3 00:54
你的程序现在的执行逻辑是这样的:

一开始flag为false,消费者进out,上锁,判断while为真,进入循环, ...

明白了,谢谢这么耐心的回答




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2