动力节点首页 全国咨询热线:400-8080-105

绑定手机号,登录
手机号

验证码

微信登录
手机号登录
手机号

验证码

微信登录与注册
微信扫码登录与注册

扫码关注微信公众号完成登录与注册
手机号登录
首页 > 文章

线程死锁分析

04-13 18:21 928浏览
举报 T字号
  • 大字
  • 中字
  • 小字

什么是线程死锁?

死锁是指两个或者两个以上的线程在执行过程中,因为争夺资源而造成的互相等待的现象。如果没有外力作用下,这些线程会一直互相等待而无法继续运行下去。比如说线程A持有资源1,等待资源2。线程B持有资源2,等待资源1。且双方都不愿意放弃自己所持有的资源。

死锁的四个条件:

  • 互斥条件:资源只能同时被一个线程占用,如果此时有其他线程想要获取资源,则必须等待,直到占有资源的线程释放该资源
  • 请求并持有条件:指一个线程已经持有了至少一个资源,但是又提出了新的资源请求,而新资源已被其他线程占用,所以当前线程会被阻塞,但是又不释放自己的资源。
  • 不可剥夺条件:指线程获取到资源在自己使用完之前不被其他线程抢占,只有在自己使用完毕之后才由自己释放该资源。
  • 环路等待条件:指在发生死锁时 必然存在一个线程-资源的环形链,比如说线程1等待线程2的资源,线程2等待线程1的资源。
public class DeadLock2 {

    private static volatile Object resourceA = new Object();
    private static volatile Object resourceB = new Object();

    public static void main(String[] args) {
        new Thread(() -> {
            synchronized (resourceA) {
                System.out.println("获取resourceA的锁");
                try {
                    Thread.sleep(1000L);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (resourceB) {
                    System.out.println("获取resourceB的锁");
                    //进入等待状态,此时会释放resource的监视器锁,但是不会释放resourceB的监视器锁
                    System.out.println("进行等待状态并释放resourceA的锁");
                }
            }
        }).start();

        new Thread(() -> {
            synchronized (resourceB) {
                try {
                    Thread.sleep(1000L);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("获取resourceB的锁");
                synchronized (resourceA) {
                    System.out.println("获取resourceA的锁");
                }
            }
        }).start();
    }
}

然后就无法继续往下执行了,进入了死锁状态

如何避免死锁?

只需要破坏掉四个死锁条件中的一个构造死锁的必要条件即可。但是只有请求并持有条件和环路等待条件是可以被破坏的。资源的互斥条件和不可剥夺条件无法被破坏。

根据资源申请的有序性原则,可以让多个线程都使用相同的顺序去获取资源。比如说之前的线程1获取资源A再获取资源B,线程2获取资源B再获取资源A,这样有可能会发生死锁但是改成,线程1先获资源A,再获取B,线程2也先获取资源A再获取资源B.这样资源A只能被一个线程获取,只有获取到了资源A的线程才会继续去获取资源B,从而避免了死锁.同时破坏了环路等待条件和请求并持有条件获取超时则放弃。

0人推荐
共同学习,写下你的评论
0条评论
代码小兵221
程序员代码小兵221

6篇文章贡献46012字

相关课程 更多>

作者相关文章更多>

推荐相关文章更多>

Java面试题及答案整理

提枪策马乘胜追击04-21 20:01

Spring常见面试题

代码小兵92504-17 16:07

Java零基础实战项目——五子棋

代码小兵98804-25 13:57

Java string类详解

杨晶珍05-11 14:54

6道经典算法面试题

杨晶珍05-12 16:39

发评论

举报

0/150

取消