美文网首页
Java基础22-多线程死锁

Java基础22-多线程死锁

作者: Tian_Peng | 来源:发表于2019-08-13 00:01 被阅读0次

概述

死锁是一个很严重的、必须要引起重视的问题。

尽管锁被持有的时间通常很短,但是作为商业产品的应用程序每天可能要执行数十亿次获取锁、释放锁的操作,只要在这数十亿次操作中只要有一次发生了错误,就可能导致程序中发生死锁,并且即使通过压力测试也不可能找出所有潜在的死锁。

死锁

当一个线程永远地持有一个锁,并且其他线程都尝试去获得这个锁时,那么它们将永远被阻塞。

如果线程A持有锁L并且想获得锁M,线程B持有锁M并且想获得锁L,那么这两个线程将永远等待下去,这种情况就是最简单的死锁形式。

在数据库系统的设计中考虑了监测死锁以及从死锁中恢复,数据库如果监测到了一组事务发生了死锁时,将选择一个牺牲者并放弃这个事务。

Java虚拟机解决死锁问题方面并没有数据库这么强大,当一组Java线程发生死锁时,这两个线程就永远不能再使用了,并且由于两个线程分别持有了两个锁,那么这两段同步代码/代码块也无法再运行了(除非终止并重启应用)。

死锁示例

下面是一个简单的多线程死锁示例:

public class DeadLock {
    private final Object left = new Object();
    private final Object right = new Object();

    public void leftRight() throws Exception {
        synchronized (left) {
            Thread.sleep(2000);
            synchronized (right) {
                System.out.println("leftRight end!");
            }
        }
    }

    public void rightLeft() throws Exception {
        synchronized (right) {
            Thread.sleep(2000);
            synchronized (left) {
                System.out.println("rightLeft end!");
            }
        }
    }
}

注意这里一定要有"Thread.sleep(2000)"让线程睡一觉,不然一个线程运行了,另一个线程还没有运行,先运行的线程很有可能就已经连续获得两个锁了。

写两个线程分别调用它们:

public class Thread0 extends Thread {
    private DeadLock dl;

    public Thread0(DeadLock dl) {
        this.dl = dl;
    }

    public void run() {
        try {
            dl.leftRight();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
public class Thread1 extends Thread {
    private DeadLock dl;

    public Thread1(DeadLock dl) {
        this.dl = dl;
    }

    public void run() {
        try {
            dl.rightLeft();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

写个main函数执行

public static void main(String[] args) {
    DeadLock dl = new DeadLock();
    Thread0 t0 = new Thread0(dl);
    Thread1 t1 = new Thread1(dl);
    t0.start();
    t1.start();

    while (true) ;
}

执行main函数将发现没有任何输出,因为死锁了!

如何避免死锁

  • 让程序每次至多只能获得一个锁。当然,在多线程环境下,这种情况通常并不现实
  • 设计时考虑清楚锁的顺序,尽量减少嵌在的加锁交互数量
  • 既然死锁的产生是两个线程无限等待对方持有的锁,那么只要等待时间有个上限不就好了。当然synchronized不具备这个功能,但是我们可以使用Lock类中的tryLock方法去尝试获取锁,这个方法可以指定一个超时时限,在等待超过该时限之后变回返回一个失败信息

相关文章

  • Java基础22-多线程死锁

    概述 死锁是一个很严重的、必须要引起重视的问题。 尽管锁被持有的时间通常很短,但是作为商业产品的应用程序每天可能要...

  • Java自学-多线程 死锁

    Java 演示多线程死锁 当业务比较复杂,多线程应用里有可能会发生死锁 步骤 1 : 演示死锁 线程1 首先占有对...

  • 照本宣科的问题

    3条你遵循的多线程最佳实践三条最佳实践我觉得大多数Java程序员都应该遵循: 如何避免死锁?Java多线程中的死锁...

  • 多线程分析——死锁代码demo

    前言 本文主要是对Java多线程死锁代码demo的分析,对其过程以及死锁进行了大致的概括,希望对大家有帮助。 死锁...

  • android 多线程 — 线程的面试题和答案

    这里都是我从各个地方找来的资料,鸣谢: Java多线程干货系列—(一)Java多线程基础 JAVA多线程和并发基础...

  • 技术体系

    一,java核心 java基础,jvm,算法,多线程,设计模式 Java基础:java基础相关,全栈java基础 ...

  • 使用JDK自带的工具jstack找出造成运行程序死锁的原因

    Java多线程编程也是Java面试中经常考察的内容。刚接触Java多线程编程的朋友们,可能会不慎写出一些会导致死锁...

  • gdb调试多线程 如何解死锁问题

    基础_多线程 Q1 gdb调试多线程 如何解死锁问题?A1 gdb基本用法 info threads(show a...

  • Java多线程目录

    Java多线程目录 Java多线程1 线程基础Java多线程2 多个线程之间共享数据Java多线程3 原子性操作类...

  • Java多线程-死锁的出现和解决

    Java多线程-死锁什么是死锁? 死锁是这样一种情形:多个线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释...

网友评论

      本文标题:Java基础22-多线程死锁

      本文链接:https://www.haomeiwen.com/subject/begcjctx.html