Java线程面试题:什么是死锁?如何避免?

简介: Java线程面试题:什么是死锁?如何避免?

Java线程面试题:什么是死锁?如何避免?

死锁是指两个或多个线程相互等待对方持有的锁而不能继续执行,造成代码无法向下进行的情况。以下是一个简单的例子:

public class DeadLockDemo {
    private static final Object lockA = new Object();
    private static final Object lockB = new Object();
    public static void main(String[] args) {
        Thread threadA = new MyThreadA();
        Thread threadB = new MyThreadB();
        threadA.start();
        threadB.start();
    }
    static class MyThreadA extends Thread {
        @Override
        public void run() {
            synchronized (lockA) {
                System.out.println("MyThreadA acquired lockA");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("MyThreadA is waiting for lockB...");
                synchronized (lockB) {
                    System.out.println("MyThreadA acquired lockB");
                }
            }
        }
    }
    static class MyThreadB extends Thread {
        @Override
        public void run() {
            synchronized (lockB) {
                System.out.println("MyThreadB acquired lockB");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("MyThreadB is waiting for lockA...");
                synchronized (lockA) {
                    System.out.println("MyThreadB acquired lockA");
                }
            }
        }
    }
}

在这个例子中,我们创建了两个线程:MyThreadA和MyThreadB,分别竞争获取 lockA 和 lockB 这两个对象的锁。MyThreadA获取到了lockA 的锁,进入临界区并休眠1秒钟,然后试图获取 lockB 的锁;而 MyThreadB 获取到了lockB 的锁,也进入临界区并休眠1秒钟,然后试图获取 lockA 的锁。由于两个线程都在等待对方释放所持有的锁,因此出现了死锁情况。

避免死锁一般采用以下策略:

  1. 避免使用多个同步锁,尽量减少竞争情况;
  2. 保证获取锁的顺序,从而避免循环依赖;
  3. 使用定时锁来限制等待时间,超过一定时间后释放资源重新尝试获取。

修改代码如下:

public class DeadLockDemo {
    private static final Object lockA = new Object();
    private static final Object lockB = new Object();
    public static void main(String[] args) {
        Thread threadA = new MyThreadA();
        Thread threadB = new MyThreadB();
        threadA.start();
        threadB.start();
    }
    static class MyThreadA extends Thread {
        @Override
        public void run() {
            synchronized (lockA) {
                System.out.println("MyThreadA acquired lockA");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("MyThreadA is waiting for lockB...");
                synchronized (lockB) {
                    System.out.println("MyThreadA acquired lockB");
                }
            }
        }
    }
    static class MyThreadB extends Thread {
        @Override
        public void run() {
            //保证获取锁的顺序,从而避免循环依赖
            synchronized (lockA) {
                System.out.println("MyThreadB acquired lockA");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("MyThreadB is waiting for lockB...");
                synchronized (lockB) {
                    System.out.println("MyThreadB acquired lockB");
                }
            }
        }
    }
}

在 MyThreadB 中修改了竞争锁的获取顺序,使其先获取 lockA 的锁,从而解除了死锁情况。

总结:死锁是一种常见的并发问题,可以通过避免使用多个同步锁、保证获取锁的顺序和使用定时锁等策略来避免。在进行并发编程时,应当尽量避免出现死锁问题,以保障程序运行的稳定性和正确性。

相关文章
|
5月前
|
JSON 网络协议 安全
【Java】(10)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
269 1
|
5月前
|
JSON 网络协议 安全
【Java基础】(1)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
287 1
|
6月前
|
数据采集 存储 弹性计算
高并发Java爬虫的瓶颈分析与动态线程优化方案
高并发Java爬虫的瓶颈分析与动态线程优化方案
Java 数据库 Spring
249 0
|
6月前
|
算法 Java
50道java集合面试题
50道 java 集合面试题
|
6月前
|
算法 Java
50道java基础面试题
50道java基础面试题
|
6月前
|
算法 Java
Java多线程编程:实现线程间数据共享机制
以上就是Java中几种主要处理多线程序列化资源以及协调各自独立运行但需相互配合以完成任务threads 的技术手段与策略。正确应用上述技术将大大增强你程序稳定性与效率同时也降低bug出现率因此深刻理解每项技术背后理论至关重要.
438 16
|
7月前
|
缓存 并行计算 安全
关于Java多线程详解
本文深入讲解Java多线程编程,涵盖基础概念、线程创建与管理、同步机制、并发工具类、线程池、线程安全集合、实战案例及常见问题解决方案,助你掌握高性能并发编程技巧,应对多线程开发中的挑战。
|
7月前
|
数据采集 存储 前端开发
Java爬虫性能优化:多线程抓取JSP动态数据实践
Java爬虫性能优化:多线程抓取JSP动态数据实践