请教JAVA多线程中死锁的问题。

野餐先生 2013-05-08 08:32:40
package syn4;
/**
* 测试类
*/
public class TestAccount {
public static void main(String[] args) {
Accout a = new Accout();
StudentThread s = new StudentThread(a);
GenearchThread g = new GenearchThread(a);
}
}
package syn4;
/**
* 模拟学生线程
*/
public class StudentThread extends Thread {
Accout a;
public StudentThread(Accout a){
this.a = a;
start();
}
public void run(){
try{
while(true){
Thread.sleep(2000);
a.getMoney(); //取钱
}
}catch(Exception e){}
}
}
package syn4;
/**
* 家长线程
*/
public class GenearchThread extends Thread {
Accout a;
public GenearchThread(Accout a){
this.a = a;
start();
}
public void run(){
try{
while(true){
Thread.sleep(12000);
a.saveMoney(); //存钱
}
}catch(Exception e){}
}
}
package syn4;
/**
* 银行账户
*/
public class Accout {
int money = 0;
/**
* 取钱
* 如果账户没钱则等待,否则取出所有钱提醒存钱
*/
public synchronized void getMoney(){
System.out.println("准备取钱!");
try{
if(money == 0){
wait(); //等待
}
//取所有钱
System.out.println("剩余:" + money);
money -= 50;
//提醒存钱
notify();
}catch(Exception e){}
}

/**
* 存钱
* 如果有钱则等待,否则存入200提醒取钱
*/
public synchronized void saveMoney(){
System.out.println("准备存钱!");
try{
if(money != 0){
wait(); //等待
}
//取所有钱
money = 200;
System.out.println("存入:" + money);
//提醒存钱
notify();
}catch(Exception e){}
}
}


一,这是老师给的关于消费者生产者问题的代码。
二,我的理解是,当消费者取完最后一笔钱,执行wait()前,计算机分配的时间片段结束。计算机转而执行存钱的线程,存钱后notify()取钱线程,但由于此时取钱线程不处于wait()状态,notify()无效。然后计算机继续执行之前未完成的wait(),之后取钱线程遍一睡不醒,导致存钱线程循环完毕后也陷入等待状态,死锁就形成了。
三,因为对JAVA语言多线程的不熟悉,看到这段代码是糊涂万分,希望能得到一份简单易懂的解释。。。。
...全文
299 12 打赏 收藏 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
n27741 2013-05-27
  • 打赏
  • 举报
回复
我的理解是,当消费者取完最后一笔钱,执行wait()前,计算机分配的时间片段结束。计算机转而执行存钱的线程,存钱后notify()取钱线程,但由于此时取钱线程不处于wait()状态,notify()无效。然后计算机继续执行之前未完成的wait(),之后取钱线程遍一睡不醒,导致存钱线程循环完毕后也陷入等待状态,死锁就形成了。 当取钱完成之后,此时,存钱线程的断点在 wait()这里! 直到,取钱线程调用了notify 存钱现场才离开wait(),执行一个存钱的动作,而此时,取钱的线程的断点在 getMoney的wait 处。 不会死锁 如果你想死锁, 要抢夺多个资源。
风吹得好舒服 2013-05-24
  • 打赏
  • 举报
回复
不会产生死锁。。。
ZHXDD 2013-05-24
  • 打赏
  • 举报
回复
public synchronized void getMoney(){ System.out.println("准备取钱!"); try{ if(money == 0){ wait(); //等待 } 看这一些代码,如果money为0的话你就要等待了,等待过程中是占有锁的,另一个线程是取不到这个锁的,而此时线程也是没有办法执行notify操作的,就死锁了。 public synchronized void saveMoney(){ System.out.println("准备存钱!"); try{ if(money != 0){ wait(); //等待 } 还有这个,都是一样的效果。
阿_-_东 2013-05-09
  • 打赏
  • 举报
回复
据我分析,不会有死锁的可能,wait()是会释放锁的。莫非楼主运行出现死锁?不可能吧
nmyangym 2013-05-09
  • 打赏
  • 举报
回复
引用 3 楼 andycpp 的回复:
[quote=引用 1 楼 nmyangym 的回复:] "我的理解是,当消费者取完最后一笔钱,执行wait()前,计算机分配的时间片段结束。计算机转而执行存钱的线程," 上面这句话, 消费者在synchronized void getMoney()这个同步方法里,不执行wait()语句的话,生产者因为得不到同步对象的锁,会在锁池池子里等待,是无法执行的。 参考一下: http://blog.csdn.net/jiafu1115/article/details/6804386
这位高手,你给的链接有个图,说线程有7种状态,但是《Java核心技术》这本书中说Java线程只有6种状态,以下是原文:
Threads can be in one of six states:
•New
• Runnable
• Blocked
•Waiting
• Timed waiting
•Terminated
Once you invoke the start method, the thread is in the runnable state. A runnable 
thread may or may not actually be running. It is up to the operating system to give 
the thread time to run. (The Java specification does not call this a separate state, 
though. A running thread is still in the runnable state.) 
[/quote] 我给的例子中,runnable 状态分开了。runnable and running. "Once you invoke the start method, the thread is in the runnable state. A runnable thread may or may not actually be running."
晓风吹雾 2013-05-09
  • 打赏
  • 举报
回复
1 wait 的虚假唤醒是存在的,建议放到循环中执行。 2 以下是简单jdk上面建议的生产者消费者的例子,使用ReentrantLock和condition来写。

class BoundedBuffer {
   final Lock lock = new ReentrantLock();
   final Condition notFull  = lock.newCondition(); 
   final Condition notEmpty = lock.newCondition(); 

   final Object[] items = new Object[100];
   int putptr, takeptr, count;

   public void put(Object x) throws InterruptedException {
     lock.lock();
     try {
       while (count == items.length) 
         notFull.await();
       items[putptr] = x; 
       if (++putptr == items.length) putptr = 0;
       ++count;
       notEmpty.signal();
     } finally {
       lock.unlock();
     }
   }

   public Object take() throws InterruptedException {
     lock.lock();
     try {
       while (count == 0) 
         notEmpty.await();
       Object x = items[takeptr]; 
       if (++takeptr == items.length) takeptr = 0;
       --count;
       notFull.signal();
       return x;
     } finally {
       lock.unlock();
     }
   } 
 }
liangwenjiecp 2013-05-09
  • 打赏
  • 举报
回复
绝对不会有死锁!!
TheQueenOfJava 2013-05-09
  • 打赏
  • 举报
回复
说一下我的理解: 首先这里没有死锁,只有死循环,是很简单的生产者-消费者模拟。 wait()表示让出CPU使用权,让CPU执行其他thread,同时释放对象锁。 Account对象,分别有两个synchronized的方法,表示调用此方法时,account对象被锁定。 生产者,和消费者的构造方法里,调用了start()启动线程。 在测试类里, new了两个对象,其实只启动了2个thread(不算main线程) 1)当消费者第一次取钱时,money==0,此线程wait(),释放account对象 2)生产者存钱,存完一笔后,调用notify()唤醒其他线程,唤醒消费者。此时有2个线程同时使用CPU,但是money!=0时,生产者wait() 3)消费者享有CPU使用权,每次去50,每次调notify()唤醒生产者线程,但money!=0时,生产者继续wait() ... LZ明白了吗?
书断华 2013-05-08
  • 打赏
  • 举报
回复
要是硬要说会出现死锁,我觉得那有可能是没有吧存钱或者取钱线程唤醒,而是唤醒了别的线程。那么就可能出现死锁了.
andycpp 2013-05-08
  • 打赏
  • 举报
回复
引用 1 楼 nmyangym 的回复:
"我的理解是,当消费者取完最后一笔钱,执行wait()前,计算机分配的时间片段结束。计算机转而执行存钱的线程," 上面这句话, 消费者在synchronized void getMoney()这个同步方法里,不执行wait()语句的话,生产者因为得不到同步对象的锁,会在锁池池子里等待,是无法执行的。 参考一下: http://blog.csdn.net/jiafu1115/article/details/6804386
这位高手,你给的链接有个图,说线程有7种状态,但是《Java核心技术》这本书中说Java线程只有6种状态,以下是原文:
Threads can be in one of six states:
•New
• Runnable
• Blocked
•Waiting
• Timed waiting
•Terminated
Once you invoke the start method, the thread is in the runnable state. A runnable 
thread may or may not actually be running. It is up to the operating system to give 
the thread time to run. (The Java specification does not call this a separate state, 
though. A running thread is still in the runnable state.) 
andycpp 2013-05-08
  • 打赏
  • 举报
回复
引用 楼主 luang4322551 的回复:
我的理解是,当消费者取完最后一笔钱,执行wait()前,计算机分配的时间片段结束。计算机转而执行存钱的线程
这么理解不对吧,执行wait()前,不可能切换线程,因为都是加锁的。 你这程序我感觉不会死锁,挺正常一个程序,请其他高手鉴定
nmyangym 2013-05-08
  • 打赏
  • 举报
回复
"我的理解是,当消费者取完最后一笔钱,执行wait()前,计算机分配的时间片段结束。计算机转而执行存钱的线程," 上面这句话, 消费者在synchronized void getMoney()这个同步方法里,不执行wait()语句的话,生产者因为得不到同步对象的锁,会在锁池池子里等待,是无法执行的。 参考一下: http://blog.csdn.net/jiafu1115/article/details/6804386

62,620

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧