当前位置:   article > 正文

线程死锁及解决办法_线程拿到锁的时候报错

线程拿到锁的时候报错

线程死锁及解决办法

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();
    }
}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63

3. 解决办法:

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

@Override
public void run() {
/*        if(flag==0){
        eatMeat();
    }else{
        eatVegetable();
    }*/
    eatMeat();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

将多个锁组成一组并放到同一个锁下。前面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();
    }
}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop】
推荐阅读
相关标签
  

闽ICP备14008679号