#详细介绍!!! 造成死锁的原因以及解决方案!

这篇具有很好参考价值的文章主要介绍了#详细介绍!!! 造成死锁的原因以及解决方案!。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

本篇主要是介绍什么是死锁,已经死锁产生的原因,如果避免死锁。根据上述的几个问题让我们来阅读本篇文章。

目录

1. 什么是死锁

2. 形成死锁的原因(四个必要条件)

3. 如果有效避免死锁



#详细介绍!!! 造成死锁的原因以及解决方案!


 文章来源地址https://www.toymoban.com/news/detail-419311.html

1. 什么是死锁

死锁主要是锁彼此间进行锁等待,导致每个锁都不能正常执行的情况

例子1:多个锁相互等待造成死锁

假设有两个锁对象为lock1,lock2

线程t1对lock1进行加锁操作,在lock1加锁操作中多lock2再进行加锁操作

线程t2先对lock2进行加锁操作,在lock2加锁操作中又对lock1进行加锁

此时就会造成死锁

伪代码:

public class Demo3 {
    public static void main(String[] args) {
        Object lock1 = new Object();
        Object lock2 = new Object();
        Thread t1 = new Thread(() -> {
            while(true){
                synchronized (lock1){
                    synchronized (lock2){
                        System.out.println("hello t1");
                    }
                }
            }
        });

        Thread t2 = new Thread(() -> {
            while(true){
                synchronized (lock2){
                    synchronized (lock1){
                        System.out.println("hello t2");
                    }
                }
            }
        });

        t1.start();
        t2.start();
    }
}

上述代码则必然会造成死锁

t1 和  t2 线程同时执行

当t1线程对lock1加锁成功了之后,此时lock1已经被占用了,然后t2线程对lock2加锁成功了,此时lock2已经被占用了;

在这种情况下,t1线程在去尝试对lock2进行加锁则会进行锁等待,因为lock2进行被线程t2占用了,那么此时t2线程去尝试对lock1进行加锁也是同理,此时t1占用个lock1不放,t2占用着lock2不放,导致对方都拿不到锁进行等待,那么此时t1和t2线程就不能向下执行死锁了

例子2:同一个线程对同一个锁进行加锁并且该锁是不可重入锁,自己给自己进行锁等待,必然死锁

假设有一个锁lock

代码:

public class Demo4 {
    public static void main(String[] args) {
        Object lock = new Object();
        int a = 0;
        int b = 0;
        synchronized (lock){
            a++;
            synchronized (lock){
                b++;
            }
        }
    }
}

如果是不可重入锁的话上面代码必然死锁

原因,第一次对lock加锁,是此时lock已经被自己占用了,第二次再对lock加锁则发现lock已经被占用此时进行等待lock释放,但是线程已经锁等待了,此时肯定是等不到lock释放的,则造成死锁

注意:由于synchronized是可重入锁,所以上述代码并不会死锁,上面代码只是举个例子说明这种情况

2. 形成死锁的原因(四个必要条件)

本质原因就是,锁之间进行相互等待,等待不到也不会释放手中的资源,相互进行死等导致死锁

而造成这样的底层原因为如下几点:

1. 互斥使用:锁的特性是每次只能有一个线程对锁进行使用,当锁没解锁时,锁资源不会被其他线程正常获取到

2. 不可抢占:资源请求者不能从资源占用者那里抢占到资源,资源只能被占用者主动释放后,请求者才能去获取资源

3. 请求和保持:锁资源请求者在请求其他锁资源时,会保持手中锁资源的占用

如上面例1,t1占用了lock1,再去请求lock2时会仍然占用这lock1,导致其他请求者获取不到

4. 循环等待:线程之间循环占用着彼此的资源,导致彼此间都获取不到资源去正常运行导致死锁

如上面例1:t1占用这个lock1,且正在亲请求lock2,t2占用这lock2,且正在请求lock1;

此时t1占用着t2请求的资源,t2占用着t1请求的资源,这样形成了一个请求闭环,导致相互拿不到资源进而死锁

注意:只要形成了死锁,则必然满足上面四个条件

3. 如果有效避免死锁

既然需要避免死锁,那么就需要根据造成死锁的原因入手。根据上面四条必要条件

1,2点是锁为了保证线程安全锁持有的的特性改变不了

但是3,4则是编码者自己写出来的可以避免

只要破坏了3,4点其中一条自然也就不会死锁

死锁与前面的四个原因是必要关系

方法:破坏循环等待的环路

我们只要保证加锁的顺序一致,那么环路就会得到有效的破坏

前面的例1进行改写:

把两个线程的加锁顺序改为一致

public class Demo3 {
    public static void main(String[] args) {
        Object lock1 = new Object();
        Object lock2 = new Object();
        Thread t1 = new Thread(() -> {
            while(true){
                synchronized (lock1){
                    synchronized (lock2){
                        System.out.println("hello t1");
                    }
                }
            }
        });

        Thread t2 = new Thread(() -> {
            while(true){
                synchronized (lock1){
                    synchronized (lock2){
                        System.out.println("hello t2");
                    }
                }
            }
        });

        t1.start();
        t2.start();
    }
}

此时 t1 和 t2 线程都是先对lock1进行加锁,再对lock2进行加锁,此时就不会产生资源彼此占用的环路了也就不会进行死锁等待

解析:

t1先占用了lock1锁,此时t2就获取不到lock1锁了,那么此时t2就在当前代码位置进行锁等待了,更加执行不到去尝试占用lock2锁的代码了,那么t1线程就能正常拿到lock2的锁资源了,所以此时t1和t2只会执行一个线程,不会形成请求资源的闭环。


本篇文章介绍到这里就差不多了,也欢迎各位铁铁指正文章错误的地方

#详细介绍!!! 造成死锁的原因以及解决方案!#详细介绍!!! 造成死锁的原因以及解决方案!

 #详细介绍!!! 造成死锁的原因以及解决方案!

 

 

到了这里,关于#详细介绍!!! 造成死锁的原因以及解决方案!的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • kafka千万级数据积压原因以及解决方案

    一、原因 kafka作为消息队列,其中数据积压也是经常遇到的问题之一。 我们都知道,数据积压的直接原因,一定是系统中的某个部分出现了性能问题,来不及处理上游发送的数据,才会导致数据积压。 那么我们就需要分析在使用kafka时,如何通过优化代码以及参数配置来最大

    2024年02月12日
    浏览(39)
  • Redis中的缓存穿透、雪崩、击穿的原因以及解决方案

    是指用户查询数据,在数据库没有,自然在缓存中也不会有。这样就导致用户查询的时候,在缓存中找不到,每次都要去数据库再查询一遍,然后返回空(相当于进行了两次无用的查询)。这样请求就绕过缓存直接查数据库,这也是经常提的缓存命中率问题。 我们可以简单的

    2024年02月12日
    浏览(31)
  • redis中缓存雪崩,缓存穿透,缓存击穿的原因以及解决方案

    在redis中,新,旧数据交替时候,旧数据进行了删除,新数据没有更新过来,造成在高并发环境下,大量请求查询redis没有数据,直接查询mysql,造成mysql的压力骤增,给mysql造成极大的压力,造成一连串的后续异常反应。 1.大多数系统设计者 考虑用加锁 (最多的解决方案)或

    2024年02月15日
    浏览(38)
  • 安卓之导致ANR的原因分析,问题定位以及解决方案

            在Android应用开发中,Application Not Responding(ANR)是一种常见的性能问题,它直接关系到用户体验的质量。当应用在特定时间段内无法及时响应用户的交互或者系统事件时,系统将会抛出ANR错误,提示用户应用已停止响应。为了确保应用的流畅性和用户满意度,理解

    2024年03月13日
    浏览(43)
  • Xshell连接不上排错以及解决方案(本文原因:重启网卡失败)

    目录 ​说一下我自己的排错思路: (1)检查自己想要链接的虚拟机有无开启 (2)检查windows服务里面关于虚拟机和xshell的服务是否已经开启,网络是否出错 (3)进入ens33文件查看ip ,dns1等是否出现配置错误 (4)检查防火墙有没有关闭 (5)查看ssh服务是否开启  (6)是否

    2024年02月04日
    浏览(30)
  • 电脑显示屏不亮但是主机已开机?5种原因以及解决方案

    电脑与我们的日常生活和工作密切相关,缺了它我们工作就很难正常展开。电脑使用久了,难免出现一些小问题, 比如:电脑显示屏不亮但是主机已开机,这是什么原因造成的?我们应该怎么处理? 可能很多人无从下手,但是只要我们弄清楚自己电脑出现这种情形的原因,

    2024年02月09日
    浏览(30)
  • 虚拟机ssh连接网络时显示未连接原因有哪些以及解决方案

    1.网络配置问题:虚拟机的网络配置可能不正确,如IP地址、子网掩码、网关、DNS设置等。这可能导致虚拟机无法访问网络,从而导致SSH连接失败。 2.防火墙问题:虚拟机或主机上的防火墙可能会阻止SSH连接。这可能是由于防火墙规则设置不正确或防火墙软件未正确配置所致。

    2024年02月09日
    浏览(32)
  • Mysql 死锁和死锁的解决方案

    前置知识:需要了解锁的种类,如表锁、行锁;行锁又分为记录锁、间隙锁、临键锁等等;什么情况下会加表锁,什么情况下会加行锁,什么情况下会加临键锁,什么情况锁会升级等等。。。网上讲解很多,这里就不单独讲述了 一 表死锁 产生原因: 用户A访问表A(锁住了表

    2024年02月02日
    浏览(50)
  • 什么是粘包?造成粘包的原因,解决它的方法

      🍎 个人博客: 个人主页 🏆 个人专栏: 日常聊聊 ⛳️   功不唐捐,玉汝于成 目录 前言 正文 造成粘包的原因: 解决粘包问题方法: 结语  我的其他博客 在计算机网络通信中,粘包是一种常见的问题,特别是在使用TCP协议进行数据传输时更为突出。粘包指的是发送方

    2024年04月16日
    浏览(22)
  • 160wifi开启失败解决方法以及手机连不上原因共同介绍

    现在用笔记本创建wifi热点已经不是什么稀奇的事情了。如果您懂代码,可以直接输入代码来创建wifi热点;如果您是电脑小白,借助个软件也可以很方便的实现与电脑的wifi共享。对于用户而言,160WiFi就是一个很不错的选择。下面小编将告诉您,为什么用户都选择160WiFi? 第一

    2024年02月06日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包