黑马程序员技术交流社区
标题:
多线程如何解决死锁问题?
[打印本页]
作者:
Ф福@ 御
时间:
2014-5-20 20:15
标题:
多线程如何解决死锁问题?
是不是要确认锁是什么,并且要十分清楚线程的状态?
作者:
Sevenette
时间:
2014-5-21 17:09
本帖最后由 Sevenette 于 2014-5-21 17:12 编辑
死锁一种情况是两个锁互相嵌套,运行时不和谐两个进程都掐着锁不放这是毕老师将时的例子0.0 可以愉快的copy去玩玩看...
代码应该能看懂吧0.0?视频大概是在day13-day14 (我是35天的那个视频)
class Ticket implements Runnable
{
private int num = 100;
Object obj = new Object();
boolean flag = true;
public void run()
{
if(flag)
while(true)
{
synchronized(obj)
{
show();
}
}
else
while(true)
this.show();
}
public synchronized void show()
{
synchronized(obj)
{
if(num>0)
{
try{Thread.sleep(10);}catch (InterruptedException e){}
System.out.println(Thread.currentThread().getName()+".....sale...."+num--);
}
}
}
}
class DeadLockDemo
{
public static void main(String[] args)
{
Ticket t = new Ticket();
Thread t1 = new Thread(t);
Thread t2 = new Thread(t);
t1.start();
try{Thread.sleep(10);}catch(InterruptedException e){}
t.flag = false;
t2.start();
}
}
复制代码
还有一种情况的是在同步里,生产消费模型,notify()方法唤醒本方线程造成所有线程都处于wait()状态,形成死锁。把notify()改成notifyAll()方法就能解决了~
/*
生产者,消费者。
多生产者,多消费者的问题。
if判断标记,只有一次,会导致不该运行的线程运行了。出现了数据错误的情况。
while判断标记,解决了线程获取执行权后,是否要运行!
notify:只能唤醒一个线程,如果本方唤醒了本方,没有意义。而且while判断标记+notify会导致死锁。
notifyAll解决了本方线程一定会唤醒对方线程的问题。
*/
class Resource
{
private String name;
private int count = 1;
private boolean flag = false;
public synchronized void set(String name)//
{
while(flag)
try{this.wait();}catch(InterruptedException e){}// t1 t0
this.name = name + count;//烤鸭1 烤鸭2 烤鸭3
count++;//2 3 4
System.out.println(Thread.currentThread().getName()+"...生产者..."+this.name);//生产烤鸭1 生产烤鸭2 生产烤鸭3
flag = true;
notifyAll();
}
public synchronized void out()// t3
{
while(!flag)
try{this.wait();}catch(InterruptedException e){} //t2 t3
System.out.println(Thread.currentThread().getName()+"...消费者........"+this.name);//消费烤鸭1
flag = false;
notifyAll();
}
}
class Producer implements Runnable
{
private Resource r;
Producer(Resource r)
{
this.r = r;
}
public void run()
{
while(true)
{
r.set("烤鸭");
}
}
}
class Consumer implements Runnable
{
private Resource r;
Consumer(Resource r)
{
this.r = r;
}
public void run()
{
while(true)
{
r.out();
}
}
}
class ProducerConsumerDemo
{
public static void main(String[] args)
{
Resource r = new Resource();
Producer pro = new Producer(r);
Consumer con = new Consumer(r);
Thread t0 = new Thread(pro);
Thread t1 = new Thread(pro);
Thread t2 = new Thread(con);
Thread t3 = new Thread(con);
t0.start();
t1.start();
t2.start();
t3.start();
}
}
复制代码
或者运用1.5的新特性:Lock和Condition解决。只有Resource资源类中的方法有改动 生产、消费类的代码和上面是一样的 我就不粘贴了0.0
/*
jdk1.5以后将同步和锁封装成了对象。
并将操作锁的隐式方式定义到了该对象中,
将隐式动作变成了显示动作。
Lock接口: 出现替代了同步代码块或者同步函数。将同步的隐式锁操作变成现实锁操作。
同时更为灵活。可以一个锁上加上多组监视器。
lock():获取锁。
unlock():释放锁,通常需要定义finally代码块中。
Condition接口:出现替代了Object中的wait notify notifyAll方法。
将这些监视器方法单独进行了封装,变成Condition监视器对象。
可以任意锁进行组合。
await();
signal();
signalAll();
*/
import java.util.concurrent.locks.*;
class Resource
{
private String name;
private int count = 1;
private boolean flag = false;
// 创建一个锁对象。
Lock lock = new ReentrantLock();
//通过已有的锁获取该锁上的监视器对象。
// Condition con = lock.newCondition();
//通过已有的锁获取两组监视器,一组监视生产者,一组监视消费者。
Condition producer_con = lock.newCondition();
Condition consumer_con = lock.newCondition();
public void set(String name)// t0 t1
{
lock.lock();
try {
while(flag)
// try{lock.wait();}catch(InterruptedException e){}// t1 t0
try{producer_con.await();}catch(InterruptedException e){}// t1 t0
this.name = name + count;//烤鸭1 烤鸭2 烤鸭3
count++;//2 3 4
System.out.println(Thread.currentThread().getName()+"...生产者5.0..."+this.name);//生产烤鸭1 生产烤鸭2 生产烤鸭3
flag = true;
// notifyAll();
// con.signalAll();
consumer_con.signal();
}finally
{
lock.unlock();
}
}
public void out()// t2 t3
{
lock.lock();
try
{
while(!flag)
// try{this.wait();}catch(InterruptedException e){} //t2 t3
try{cousumer_con.await();}catch(InterruptedException e){} //t2 t3
System.out.println(Thread.currentThread().getName()+"...消费者.5.0......."+this.name);//消费烤鸭1
flag = false;
// notifyAll();
// con.signalAll();
producer_con.signal();
}
finally
{
lock.unlock();
}
}
}
复制代码
作者:
艮昕辶
时间:
2014-5-21 17:12
标题:
红色代码比较关键 其他的东西换个场景就不能按老毕的写了
本帖最后由 艮昕辶 于 2014-5-21 17:16 编辑
<font color="#ff0000">Lock lock = new ReentrantLock();</font>
//通过已有的锁获取两组监视器,一组监视生产者,一组监视消费者。
<font color="#ff0000"> Condition producer_con = lock.newCondition();
Condition consumer_con = lock.newCondition();</font>
public void set(String name)// t0 t1
{
<font color="#ff0000"> lock.lock();</font>
try
{
while(flag)
try{<font color="#ff0000">producer_con.await();</font>}catch(InterruptedException e){}// t1 t0
this.name = name + count;//烤鸭1 烤鸭2 烤鸭3
count++;//2 3 4
System.out.println(Thread.currentThread().getName()+"...生产者5.0..."+this.name);//生产烤鸭1 生产烤鸭2 生产烤鸭3
flag = true;
<font color="#ff0000"> consumer_con.signal();</font>
}
finally
{
<font color="#ff0000"> lock.unlock();</font>
}
}
public void out()// t2 t3
{
<font color="#ff0000"> lock.lock();</font>
try
{
try{cousumer_con.await();}catch(InterruptedException e){} //t2 t3
System.out.println(Thread.currentThread().getName()+"...消费者.5.0......."+this.name);//消费烤鸭1
flag = false;
<font color="#ff0000">producer_con.signal();</font>
}
finally
{
<font color="#ff0000"> lock.unlock();</font>
}
}
复制代码
作者:
Ф福@ 御
时间:
2014-5-21 20:24
谢谢、指导!!!!
作者:
Hosing
时间:
2014-7-3 15:56
synchronized同步
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2