您当前的位置:首页 > 电脑百科 > 电脑知识

避免死锁危险

时间:2020-12-25 11:25:28  来源:  作者:

在并发环境中,我们为了保证共享可变数据的线程安全性,需要使用加锁机制,如果锁使用不当可能会引起死锁,线程饥饿等问题。

JAVA应用程序中如果发生死锁,程序是无法自动恢复的,严重会造成程序崩溃,所以开发中在设计阶段就要规避死锁发生的情况。

 

什么是死锁

 

死锁:每个线程拥有其他线程需要的资源,同时又等待其他线程拥有的资源,并且每个线程在获得所需要的资源前都不会放弃已经拥有的资源。

程序死锁发生的场景:

1)交叉锁导致死锁

在线程A持有锁L并想获取锁R的同时,线程B持有锁R并尝试获得锁L,那么这两个线程将永远的阻塞下去。交叉锁的发生一般是因为线程以不同的顺序获取锁。

2)资源死锁

内存不足或者我们在程序中使用了线程池和信号量对资源进行限制时,两个线程互相等待彼此释放资源而进入永久阻塞。

3)死循环死锁

程序由于代码缺陷或者重试机制而使代码陷入死循环,造成了内存和cpu的大量消耗而使线程进入阻塞。

当Java程序发生死锁时,阻塞的线程将永远不能使用了,而且可能造成程序停止或者使CPU飙高使程序性能很差。恢复程序的唯一方式就是重启应用。

死锁的发生大多数是偶然情况,并不代表一个类发生死锁,它就一直死锁,这也是死锁难以排查的原因。

通过死锁发生的场景我们可以总结出死锁发生的条件:

  • 互斥:即锁具有排他性,只有一个线程能够获取锁;
  • 占有且等待:线程获取到锁时,如果需要的资源没有获取到将一直阻塞等待需要的资源;
  • 不可抢占:获取锁的线程持有的资源不能被其他线程抢占;
  • 循环等待:陷入死锁等待的线程一定是形成了一个循环等待环路。

 

死锁的检测

 

如果一个程序一次最多获得一个锁,那么就不会发生死锁问题,但是开发中经常出现程序需要获取多个锁的场景,那么这个时候就必须考虑锁的顺序问题。

如果所有的线程以固定的顺序获取锁也是不会出现死锁问题的,当线程试图以不同的顺序来获取锁时,死锁将会发生。

下面的示例将会发生死锁:

public class DeadlockTest {
    //创建两个锁对象
    private final Object leftMonitor = new Object();
    private final Object rightMonitor = new Object();
    /**
     * 持有L锁想要获取R锁
     */
    @SneakyThrows
    public void leftForRight() {
        synchronized (leftMonitor){
            //休眠一下,给R加锁的机会
            TimeUnit.SECONDS.sleep(1);
            synchronized (rightMonitor){
                System.out.println("leftForRight获取到锁");
            }
        }
    }

    /**
     * 持有R锁获取L锁
     */
    public void rightForLeft() {
        synchronized (rightMonitor){
            synchronized (leftMonitor){
                System.out.println("rightForLeft获取到锁");
            }
        }
    }

    public static void main(String[] args) {
        DeadlockTest deadlockTest = new DeadlockTest();
        ExecutorService executor = Executors.newFixedThreadPool(2);
        executor.execute(()->{
            deadlockTest.leftForRight();
        });
        executor.execute(()->{
            deadlockTest.rightForLeft();
        });
        executor.shutdown();

    }

}

我们可以通过JDK提供的jstack或者jconsole工具查看死锁信息。

jstack -l pid查看堆栈信息:

避免死锁危险

 

或者jconsole连接到进程上:

避免死锁危险

 


避免死锁危险

 

通过堆栈信息能够很直接看到死锁信息。

linux环境下dump出堆栈信息的方法我们后续再聊。

 

死锁的避免

 

我们可以通过打破死锁发生的条件来避免死锁。

程序中的业务要求我们必须使用独占锁而不能使用共享锁,那我们就不能打破锁的互斥性。

破坏占有且等待:一次性申请所有资源;

破坏不可抢占:使用显示锁Lock中的tryLock功能来代替内置锁synchronized,可以检测死锁和从死锁中恢复过来。使用内置锁的线程获取不到锁会被阻塞,而显式锁可以指定一个超时时限(Timeout),在等待设置的时间后tryLock就会返回一个失败信息,也会释放其拥有的资源。

破坏循环等待:使线程按照固定的顺序获取锁,在设计中我们应尽量减少锁的交互数量,提前设计好锁的顺序并严格遵守。

 

结束语

 

并发编程系列基础知识的学习到此结束了,后续如果遇到相关的知识再补充。

下一个系列《Java基础》扬帆启航,类加载、数据结构(包括线程安全的数据结构)、泛型等知识将与你相遇。

祝大家圣诞节快乐!!



Tags:死锁   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
前言最近老顾经常碰到同事说,mysql又死锁了导致业务报错。今天我们就来聊聊死锁以及怎么解决锁类型mysql锁级别:页级、表级、行级表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发...【详细内容】
2021-09-06  Tags: 死锁  点击:(84)  评论:(0)  加入收藏
生产上偶现这段代码会出现死锁,死锁日志如下。*** (1) TRANSACTION:TRANSACTION 424487272, ACTIVE 0 sec fetching rowsmysql tables in use 3, locked 3LOCK WAIT 6 lock s...【详细内容】
2021-07-29  Tags: 死锁  点击:(65)  评论:(0)  加入收藏
一、前言最近参加了几轮面试,发现很多5-7年工作经验的候选人在性能优化这一块,基本上只能说出传统的分析方式,例如ANR分析,是通过查看/data/anr/ 下的log,分析主线程堆栈、cpu、...【详细内容】
2021-06-17  Tags: 死锁  点击:(149)  评论:(0)  加入收藏
一.业务背景我们现在的业务是一款数据产品,有不少实时计算和爬取来的数据都汇总到大数据仓库、数据挖掘平台ODPS上。然后应用在读取这些数据时,这些数据会先导入到并发读能力...【详细内容】
2021-04-12  Tags: 死锁  点击:(209)  评论:(0)  加入收藏
最近遇到一个由于唯一性索引,导致并发插入产生死锁的场景,在分析死锁产生的原因时,发现这一块还挺有意思的,涉及到MySql中不少的知识点,特此总结记录一下。 一、MySql常见的锁谈...【详细内容】
2021-02-19  Tags: 死锁  点击:(168)  评论:(0)  加入收藏
01. Mysql 事务死锁现象及原因初步判断做IT的几乎每天都接触 MySql,但是 Mysql 事务死锁却并不常见,前段时间就让我遇到了。异常日志如下 从日志看是发生了 Lock wait timeout...【详细内容】
2021-01-27  Tags: 死锁  点击:(205)  评论:(0)  加入收藏
在并发环境中,我们为了保证共享可变数据的线程安全性,需要使用加锁机制,如果锁使用不当可能会引起死锁,线程饥饿等问题。在Java应用程序中如果发生死锁,程序是无法自动恢复的,严重...【详细内容】
2020-12-25  Tags: 死锁  点击:(131)  评论:(0)  加入收藏
导读本文介绍Java诸多优化实例:第一,排查堆上、堆外内存泄露;第二,使用arthas、jaeger、tcpdump、jstack做性能优化;第三,排查进程异常退出的原因,如被杀、System.exit、Java调用的...【详细内容】
2020-11-25  Tags: 死锁  点击:(78)  评论:(0)  加入收藏
死锁 思维导图是什么线程死锁是指由于两个或者多个线程互相持有对方所需要的资源,导致这些线程处于等待状态,无法前往执行。当线程进入对象的synchronized代码块时,便占有了资...【详细内容】
2020-10-28  Tags: 死锁  点击:(124)  评论:(0)  加入收藏
死锁死锁的原理非常简单,用一句话就可以描述完。就是当多线程访问多个锁的时候,不同的锁被不同的线程持有,它们都在等待其他线程释放出锁来,于是便陷入了永久等待。比如A线程持...【详细内容】
2020-08-25  Tags: 死锁  点击:(55)  评论:(0)  加入收藏
▌简易百科推荐
回答这个问题前首先要了解一度电的定义一度电= 1000W·h ,是一个能量单位,一个功率为1000w的设备持续运作一小时就会消耗1度电。所以台式机多少时间一度电完全取决于台...【详细内容】
2021-12-20  数码榜    Tags:台式电脑   点击:(5)  评论:(0)  加入收藏
你是不是很多时候都会紧急冲向电源插座以拯救笔记本电脑的电量?很多时候由于附近没有方便的插座,一是会误事,二是会导致尴尬。幸运的是,现代笔记本电脑比前辈高效得多。如今,即...【详细内容】
2021-12-16  趣玩公社    Tags:电池   点击:(17)  评论:(0)  加入收藏
电脑在我们生活中的重要性不言而喻。如何保证自己的电脑流畅好用,对于很多用户来说都非常重要。作为一个理科男和IT从业者,对于自己的电脑还是非常在意的,会定期的进行整理,保持...【详细内容】
2021-12-09  小伊评科技    Tags:电脑   点击:(13)  评论:(0)  加入收藏
大家好,我是良许。不管我们使用什么操作系统,无论是 Windows、macOS 还是 Linux ,里面都安装了许多软件、驱动程序和固件。但是,这三者概念有区别呢?我在朋友圈做了个小调查,发现...【详细内容】
2021-11-30  良许Linux    Tags:固件   点击:(10)  评论:(0)  加入收藏
澎湃问吧世界著名密码史学家戴维·卡恩曾说:“人类使用密码的历史几乎与使用文字的时间一样长”,这意味着人类密码领域的较量已近五千年。提及“密码”一词,大多数人会想...【详细内容】
2021-11-24    澎湃新闻  Tags:密码   点击:(16)  评论:(0)  加入收藏
由于去中心化域名和账户体系可以承载应用、网站和用户身份,因此有理由相信,这是 Web3 世界中不可或缺的一环。撰文:潘致雄如果回忆一下初次进行的加密货币转账时的体验,特别是在...【详细内容】
2021-11-03  链闻ChainNews    Tags:ENS   点击:(26)  评论:(0)  加入收藏
 文件系统(File System)是计算机系统必不可少的组成部分,可以说除了部分结构简单的单片机系统之外,文件系统是支撑每一个计算机系统运行的最重要的支撑,无论是操作系统、应用程...【详细内容】
2021-11-01  欧工玩转嵌入式  CSDN  Tags:FAT32   点击:(30)  评论:(0)  加入收藏
SDS 2.0时代进化达尔文的《进化论》认为,地球上现存的所有生物都是自然选择的结果,生物只有适应环境的变化,才能得到生存和进化。回望到企业存储,一个常做常新的行业,从上古结绳...【详细内容】
2021-10-28  ExponTech   企鹅号  Tags:SDS   点击:(35)  评论:(0)  加入收藏
在昨天的微信《远程办公危机四伏,到底该pick谁给你保驾护航?》中介绍了远程员工应该具备的四大安全工具,今天继续分享干货:05 双因子令牌在理想的情况下,每个人都会对所有的关键...【详细内容】
2021-10-26    计算机世界  Tags:远程办公   点击:(32)  评论:(0)  加入收藏
今天几乎所有的数字显示设备都基于某种类型的 RGB(红、绿、蓝)颜色模型。RGB 是表示人类可以看到的大多数颜色的最有效方式(有一些颜色不能很好地产生,但这是另一个讨论)。相机...【详细内容】
2021-10-09  懒懒散散的程序员    Tags:RGB   点击:(49)  评论:(0)  加入收藏
最新更新
栏目热门
栏目头条