内存飙升,罪魁祸首竟是死锁,这样检测和处理减少一半加班时间( 二 )

运行结果:
发现做饭【煮粥】和洗菜是同时开始的,通过细化锁,可以提升程序性能,必须要保障两个操作没有关联性,比如煮粥不需要等菜洗好,如果是炒菜,就需要等待菜洗好才可以进行 。
 

内存飙升,罪魁祸首竟是死锁,这样检测和处理减少一半加班时间

文章插图
 
锁细粒度化的好处是:提高程序等性能,弊端在于:如果一个线程同时需要多把锁,就可能产生死锁
死锁现象以上边的企业和面试者为例演示死锁,企业招工需要有工作经验的程序员,但是添甄刚毕业,没有工作经验,需要有工作才能获取工作经验,这样就导致企业招不到人,面试者找不到工作的尴尬境地!
分析
  • 这里有两个条件,一个是工作经验,一个是工作
  • 企业先验证面试者是否有工作经验,才会给工作机会
  • 面试者需要先获取工作,才能还有工作经验
  • 两者如果僵持不下,就会产生死锁
代码实现package com.tianzhen.thread;public class Deadhread {// 工作锁private static Object work = new Object();// 工作经验锁private static Object workExperience = new Object();public static void main(String[] args) {// 企业线程new Thread(() -> {// 先锁定工作经验synchronized (workExperience) {System.out.println(Thread.currentThread().getName() + "我们需要有工作经验的");// 给工作机会synchronized (work) {System.out.println(Thread.currentThread().getName() + "恭喜你通过面试加入我们");}}},"企业线程:").start();// 员工线程new Thread(() -> {// 先获取工作机会synchronized (work) {System.out.println(Thread.currentThread().getName() + "我需要工作才能有工作经验");// 有工作经验synchronized (workExperience) {System.out.println(Thread.currentThread().getName() + "通过面试获得了工作经验");}}},"面试者线程:").start();}}【内存飙升,罪魁祸首竟是死锁,这样检测和处理减少一半加班时间】运行结果:发现程序再企业和面试者各输出一句之后卡死不动
 
内存飙升,罪魁祸首竟是死锁,这样检测和处理减少一半加班时间

文章插图
 
原因 
内存飙升,罪魁祸首竟是死锁,这样检测和处理减少一半加班时间

文章插图
 
图解 
内存飙升,罪魁祸首竟是死锁,这样检测和处理减少一半加班时间

文章插图
 
简单的说就是:我需要的东西你占着,你需要的东西我占着,而且我们都不会脑筋急转弯,就傻傻的等着对方让步,拿到自己需要的东西之后继续玩,但是大家都这么想那就谁也别玩了 。
死锁产生的四个必要条件
  • 互斥使用:即当资源被一个线程使用(占有)时,别的线程不能使用
  • 不可抢占:资源请求者不能强制从资源占有者手中夺取资源,资源只能由资源占有者主动释放
  • 请求和保持:即当资源请求者在请求其他的资源的同时保持对原有资源的占有
  • 循环等待:即存在一个等待队列:企业线程占有workExperience锁资源,面试者线程占有 work锁 资源,面试者线程需要workExperience锁资源,企业线程需要work锁资源,彼此等待对方释放资源 。这样就形成了一个等待环路
当上述四个条件都成立的时候,便形成死锁 。当然,死锁的情况下如果打破上述任何一个条件,便可让死锁消失 。
死锁检测死锁检测其实非常简单,这里介绍两种方式监测死锁,如果你有更好的办法或工具记得在评论区分享哦!
方式1:命令检测
  • 死锁就会导致程序卡死不动,它的特点就是占用内存比较多,首先找到占用内存多的Java进程
  • 其次通过jps命令找到对应的java进程号
  • 通过jstack 进程号得到进程信息
  • 通过进程信息查看是否是死锁,发生在什么地方
1、window下通过任务管理器查看进程内存占用情况,linux下通过 top 命令查看,这里以window为例
 
内存飙升,罪魁祸首竟是死锁,这样检测和处理减少一半加班时间

文章插图
 
2、通过jps命令获取该进程的进程号也就是PID
 
内存飙升,罪魁祸首竟是死锁,这样检测和处理减少一半加班时间

文章插图


推荐阅读