死锁——从产生到消除

1、死锁是什么?

  • 发生在并发中

  • 互不相让:当两个(当两个(或更多)线程(或进程)相互持有对方所需的资源,又不主动释放,导致所有人都无法继续前进,导致程序陷入无尽的阻塞,这就是死锁)

死锁——从产生到消除

 

2、多个线程造成死锁的情况

  • 如果多个线程之间的依赖关系是环形,存在环路的锁的依赖关系,那么也就可以发生死锁

3、死锁的影响

死锁的影响在不同系统中是不一样的,这取决于系统对死锁的处理能力

  • 数据库中:检测并放弃事务

  • JVM中:无法自动处理

4、几率不高但是危害大

  • 不一定发生,但是遵循“墨菲定律”

  • 一旦发生,多是高并发场景,影响用户多

  • 整个系统崩溃,子系统崩溃,性能降低

  • 压力测试无法找出所有潜在的死锁

5、死锁的代码

package deadlock;

//描述:   必定发生死锁的情况
public class MustDeadLock implements Runnable {
    int flag = 1;

    static Object o1 = new Object();
    static Object o2 = new Object();

    public static void main(String[] args) {
        MustDeadLock r1 = new MustDeadLock();
        MustDeadLock r2 = new MustDeadLock();
        r1.flag = 1;
        r1.flag = 0;
        Thread thread1 = new Thread(r1);
        Thread thread2 = new Thread(r2);
        thread1.start();
        thread2.start();
    }

    @Override
    public void run() {
        System.out.println("flag=" + flag);
        if (flag == 1) {
            synchronized (o1) {
                try {
                    System.out.println("我拿到O1锁啦");
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (o2) {
                    System.out.println("我拿不到了");
                }
            }
        }
        if (flag == 0) {
            synchronized (o2) {
                try {
                    System.out.println("我拿了o2锁啦");
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (o1) {
                    System.out.println("拿不到了");
                }
            }
        }
    }
}
  • 当类的对象flag=1时(thread1),先锁定o1,睡眠100毫秒,然后锁定o2

  • 而thread1在睡眠的时候另一个flag=0的对象thread2线程启动,先锁定o2,睡眠100毫秒,等待thread1释放o1

  • thread1睡眠结束后需要锁定o2才能继续执行,而此时o2已被thread2锁定

  • thread2睡眠结束后需要锁定o1才能继续执行,而此时o1已被thread1锁定

  • thread1和thread2相互等待,都需要对方锁定资源才能继续执行,从而死锁

上一篇:分布式限流篇


下一篇:【java】short、byte、char进行运算时的注意点