死锁问题,大神求助啊~~~

axr1985lazy 2014-11-21 10:38:38
我这段代码就是模拟最基本的生产者和消费者的例子,为了观察线程故意做了两层嵌套的同步代码块,几乎每次都会死锁,代码如下,

//共享资源类
class Resource
{
//商品名
private String name;
//商品数量
private int count = 1;
//标记
private boolean flag = false;

//两个锁对象
private Object obj_pro = new Object();
private Object obj_con = new Object();

//生产方法,为方便观察几乎为每一步都添加了输出语句
public void produce(String name)
{
System.out.println(Thread.currentThread().getName()+"------------pro1");
//第一层同步代码块,使用obj_con锁
synchronized(obj_con)
{
System.out.println(Thread.currentThread().getName()+"------------pro2");
//第二层同步代码块,使用obj_pro锁
synchronized(obj_pro)
{
System.out.println(Thread.currentThread().getName()+"------------pro3");
//当标记为真时,表明生产了一个商品,等待
while(flag)
{
System.out.println(Thread.currentThread().getName()+"------------pro4");
//通过condition_pro对象只冻结生产者线程
try{obj_pro.wait();}catch(InterruptedException e){}
}

this.name = name+"--"+count++;

System.out.println(Thread.currentThread().getName()+"...生产者..."+this.name);
flag = true;

//只唤醒消费者线程
obj_con.notify();
System.out.println(Thread.currentThread().getName()+"------------pro5");
}
System.out.println(Thread.currentThread().getName()+"------------pro6");
}
System.out.println(Thread.currentThread().getName()+"------------pro7");
}
//消费方法
public void consume()
{
System.out.println(Thread.currentThread().getName()+"------------con1");
synchronized(obj_con)
{
System.out.println(Thread.currentThread().getName()+"------------con2");
synchronized(obj_pro)
{
System.out.println(Thread.currentThread().getName()+"------------con3");
while(!flag)
{
System.out.println(Thread.currentThread().getName()+"------------con4");
//冻结消费者线程
try{obj_con.wait();}catch(InterruptedException e){}
}

System.out.println(Thread.currentThread().getName()+"..........消费者.........."+this.name);
flag = false;

//唤醒生产者线程
obj_pro.notify();

System.out.println(Thread.currentThread().getName()+"------------con5");
}
System.out.println(Thread.currentThread().getName()+"------------con6");
}
System.out.println(Thread.currentThread().getName()+"------------con7");
}
}
//生产者
class Producer implements Runnable
{
private Resource res;
Producer(Resource res)
{
this.res = res;
}

public void run()
{
while(true)
{
res.produce("+商品+");
}
}
}
//消费者
class Consumer implements Runnable
{
private Resource res;
Consumer(Resource res)
{
this.res = res;
}

public void run()
{
while(true)
{
res.consume();
}
}
}
class ProducerConsumerDemo
{
public static void main(String[] args)
{
//创建资源类
Resource res = new Resource();

//创建生产者和消费者对象
Producer pro = new Producer(res);
Consumer con = new Consumer(res);

Thread t1 = new Thread(pro);
Thread t2 = new Thread(pro);
Thread t3 = new Thread(con);
Thread t4 = new Thread(con);
t1.start();
t2.start();
t3.start();
t4.start();
}
}


运行结果通常是这样的:
Thread-1------------pro1
Thread-2------------con1
Thread-3------------con1
Thread-0------------pro1
Thread-1------------pro2
Thread-1------------pro3
Thread-1...生产者...+商品+--1
Thread-1------------pro5
Thread-1------------pro6
Thread-1------------pro7
Thread-0------------pro2
Thread-1------------pro1
Thread-0------------pro3
Thread-0------------pro4

我的问题是,就像上面的结果那样,如果按照wait方法的特性,0号线程等待以后,将会释放其所持有的锁对象,但是为什么其他线程均止步于“pro1”或者“con1”,这表明其他三个线程压根就没有拿到锁,都没有开始执行同步代码块,难道说wait方法不会释放持有的全部锁对象吗?而是指释放最近获取的锁?希望高手指点啊~~~
...全文
106 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
W-Aires 2014-11-21
  • 打赏
  • 举报
回复
引用 3 楼 axr1985lazy 的回复:
[quote=引用 1 楼 luogui551 的回复:]

try{obj_pro.wait();}catch(InterruptedException  e){}//这句只会释放obj_pro,不会释放obj_con,所以你的消费者基本没有机会获取到obj_con
首先非常感谢大神的回复,解了燃眉之急! 其次,说明我的猜测是正确的,wait方法只会释放最近获取的锁,而不会全部释放。 第三,那么这样定义释放锁的机制的意义是什么呢?只释放一个,保留其他的是为了什么? 分先给你加上,再帮忙回答一下呗~~~[/quote] 不是就近原则,而是obj_pro.wait(),释放的就是obj_pro,假设你在这的是obj_con.wait(),那释放的就是obj_con
axr1985lazy 2014-11-21
  • 打赏
  • 举报
回复
引用 1 楼 luogui551 的回复:

try{obj_pro.wait();}catch(InterruptedException  e){}//这句只会释放obj_pro,不会释放obj_con,所以你的消费者基本没有机会获取到obj_con
首先非常感谢大神的回复,解了燃眉之急! 其次,说明我的猜测是正确的,wait方法只会释放最近获取的锁,而不会全部释放。 第三,那么这样定义释放锁的机制的意义是什么呢?只释放一个,保留其他的是为了什么? 分先给你加上,再帮忙回答一下呗~~~
W-Aires 2014-11-21
  • 打赏
  • 举报
回复
另外执行到这句的时候会阻塞线程,后面语句是执行不到的
W-Aires 2014-11-21
  • 打赏
  • 举报
回复

try{obj_pro.wait();}catch(InterruptedException  e){}//这句只会释放obj_pro,不会释放obj_con,所以你的消费者基本没有机会获取到obj_con
axr1985lazy 2014-11-21
  • 打赏
  • 举报
回复
引用 5 楼 ningbohezhijun 的回复:
我去,我还在调试代码,你把问题关了,险些就没找到问题了。
实在抱歉,因为,问题太过浅显,比人提醒一下就明白了,谢谢你的关注哈~
axr1985lazy 2014-11-21
  • 打赏
  • 举报
回复
引用 4 楼 luogui551 的回复:
[quote=引用 3 楼 axr1985lazy 的回复:] [quote=引用 1 楼 luogui551 的回复:]

try{obj_pro.wait();}catch(InterruptedException  e){}//这句只会释放obj_pro,不会释放obj_con,所以你的消费者基本没有机会获取到obj_con
首先非常感谢大神的回复,解了燃眉之急! 其次,说明我的猜测是正确的,wait方法只会释放最近获取的锁,而不会全部释放。 第三,那么这样定义释放锁的机制的意义是什么呢?只释放一个,保留其他的是为了什么? 分先给你加上,再帮忙回答一下呗~~~[/quote] 不是就近原则,而是obj_pro.wait(),释放的就是obj_pro,假设你在这的是obj_con.wait(),那释放的就是obj_con[/quote] 哦,原来是这样,哎,我自己想得太外行了。。。。,再次谢谢你!
ningbohezhijun 2014-11-21
  • 打赏
  • 举报
回复
我去,我还在调试代码,你把问题关了,险些就没找到问题了。

62,615

社区成员

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

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