线程死锁及解决办法

线程死锁及解决办法

1. 什么是死锁

所谓死锁: 是指两个或两个以上的线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的线程称为死锁线程。 由于资源占用是互斥的,当某个线程提出申请资源后,使得有关线程在无外力协助下,永远分配不到必需的资源而无法继续运行,这就产生了一种特殊现象死锁.
关键点:
1)两个以上的线程
2)争夺共享的资源
3)它们各自不释放手中资源,除非有外力协助

2. 死锁例子:

public class TestDealLock implements Runnable{

/**
 * @param args
 */
public static void main(String[] args) {
    TestDealLock lock1=new TestDealLock();
    TestDealLock lock2=new TestDealLock();
    Thread thread1=new Thread(lock1);
    Thread thread2=new Thread(lock2);
    lock1.setFlag(0);
    lock2.setFlag(1);
    thread1.start();
    thread2.start();
}

private static Object obj1=new Object();//一把A筷子的锁
private static Object obj2=new Object();//一把B筷子的锁
private int flag=0;

public int getFlag() {
    return flag;
}
public void setFlag(int flag) {
    this.flag = flag;
}
public void eatMeat(){
         synchronized (obj1) {
             System.out.println(Thread.currentThread().getName()+":拿到A筷子!");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized (obj2) {
                System.out.println(Thread.currentThread().getName()+":拿到B筷子!开始吃饭");
            }
            }
}
public void eatVegetable(){
         synchronized (obj2) {
                System.out.println(Thread.currentThread().getName()+":拿到B筷子!");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                
                synchronized (obj1) {
                    System.out.println(Thread.currentThread().getName()+":拿到A筷子!开始吃饭");
                }
            }
}

@Override
public void run() {
    if(flag==0){
        eatMeat();
    }else{
        eatVegetable();
    }
}
}

3. 解决办法:

1)、让所有的线程按照同样的顺序获得一组锁。这种方法消除了 X 和 Y 的拥有者分别等待对方的资源的问题。
2)、将多个锁组成一组并放到同一个锁下。前面Java线程死锁的例子中,可以创建一个银器对象的锁。于是在获得刀或叉之前都必须获得这个银器的锁。
3)、将那些不会阻塞的可获得资源用变量标志出来。当某个线程获得银器对象的锁时,就可以通过检查变量来判断是否整个银器集合中的对象锁都可获得。如果是,它就可以获得相关的锁,否则,就要释放掉银器这个锁并稍后再尝试。(没有实现)

@Override
public void run() {
/*        if(flag==0){
        eatMeat();
    }else{
        eatVegetable();
    }*/
    eatMeat();
}

将多个锁组成一组并放到同一个锁下。前面Java线程死锁的例子中,可以创建一个银器对象的锁。于是在获得刀或叉之前都必须获得这个银器的锁。

public class TestDealLock implements Runnable{

/**
 * @param args
 */
public static void main(String[] args) {
    TestDealLock lock1=new TestDealLock();
    TestDealLock lock2=new TestDealLock();
    Thread thread1=new Thread(lock1);
    Thread thread2=new Thread(lock2);
    lock1.setFlag(0);
    lock2.setFlag(1);
    thread1.start();
    thread2.start();
}

private static Object obj1=new Object();//一把A筷子的锁
private static Object obj2=new Object();//一把B筷子的锁
private static Object obj3=new Object();//加一把锁,保证A锁和B锁锁上同一组,只有拿到此锁才能拿到A锁或者B锁
private int flag=0;

public int getFlag() {
    return flag;
}
public void setFlag(int flag) {
    this.flag = flag;
}
public void eatMeat(){
    synchronized (obj3) {
         synchronized (obj1) {
             System.out.println(Thread.currentThread().getName()+":拿到A筷子!");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized (obj2) {
                System.out.println(Thread.currentThread().getName()+":拿到B筷子!开始吃饭");
            }
            }
    }
}
public void eatVegetable(){
    synchronized (obj3) {
         synchronized (obj2) {
                System.out.println(Thread.currentThread().getName()+":拿到B筷子!");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                
                synchronized (obj1) {
                    System.out.println(Thread.currentThread().getName()+":拿到A筷子!开始吃饭");
                }
            }
//    }
    }
}

@Override
public void run() {
    if(flag==0){
        eatMeat();
    }else{
        eatVegetable();
    }
}
}
  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值