死锁(JAVA)

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

死锁在多线程代码中是非常严重的BUG,一旦代码中出现死锁就会导致线程卡死。
单个线程连续两次同一个对象进行加锁操作时,如果该锁是不可重入锁就会发生死锁(线程卡死)

两个线程两把锁,如果出现这种情况也是会发生死锁:线程t1已经获取了锁A,线程t2已经获取了锁B,此时t1想要获取锁B,t2想要获取锁A。

Object lock1 = new Object();
Object lock2 = new Object();
 
Thread t1 = new Thread(()->{
    synchronized(lock1) {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        synchronized(lock2) {
 
        }
    }
});
Thread t2 = new Thread(()->{
    synchronized(lock2) {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        synchronized(lock1) {
 
        }
    }
});
t1.start();
t2.start();
//让主线程等待 2 秒
Thread.sleep(2000);
//此时t1和t2两个线程会因为互相争对方的锁,而导致死锁
System.out.println(t1.getState());
System.out.println(t2.getState());

死锁(JAVA),java,java-ee

如果此时有N个线程M把锁(N,M>>2),就更加容易发生死锁的情况了。

一个非常经典的N个线程M把锁的问题:哲学家就餐问题。

假设有5名哲学家围在一张桌子上吃面,现在桌子上有5根筷子。(哲学家会做两件事:思考和吃面(吃面必须要拿到两根筷子,吃完后会将筷子放回原处)。且做这两件事的时间是完全随机的,同一时间只能做一件事)
死锁(JAVA),java,java-ee
大多数情况下是不会出现问题的但也会出现一些极端情况:现在所有的哲学家都想吃面,他们同时拿起了自己左手边的筷子,此时每位哲学家手里都有且仅有一只筷子,此时每位哲学家都在等待另一支筷子就会发生死锁。
那么该如何解决死锁问题呢?首先我们先要了解死锁的必要条件,然后根据这些条件来修改。

引发死锁的必要条件

  1. 互斥(锁的基本特性);当一个线程获取到锁后,如果另一个线程也想获取该锁就会阻塞等待。
  2. 不可抢占(锁的基本特性);当线程A获取到锁后,如果线程B也想获取该锁只能等待A将该锁释放后再获取,不能直接抢。
  3. 请求保持(代码结构);一个线程获取了A锁后继续获取B锁……且前面获取的锁不进行释放。
  4. 循环等待/环路等待(代码结构);等待的依赖关系形成了环。

一个死锁代码一定会满足上述四种情况,任意一个不满足都不会形成死锁。

死锁的解决方法

解决死锁的情况只要破坏上述条件中的任意一个就行了。
上述四条中1和2都是锁的基本特性,所以无法改变。
对于3,在代码中尽量避免出现锁嵌套的情况,但是这种情况很难避免,因为实际代码中的嵌套往往都是这样的,很难发现和避免:

public void fun1(){
    synchronized (this) {
        fun2();
    }
}
public void fun2(){
    fun3();
}
public void fun3(){
    fun4();
}
public void fun4(){
    synchronized (this) {
    }
}

所以解决4就显得非常重要了,那么4这种情况该如何避免呢?
有一个非常简单的方法那就是约定加锁的顺序。
例如对于上文中的哲学家就餐的问题:
现在给每支筷子进行编号,约定每位哲学家拿筷子的顺序都是必须先拿面前编号较小的然后再拿编号较大的。
死锁(JAVA),java,java-ee
B拿1号筷子->C拿2号筷子->D拿3号筷子->E拿4号筷子->A拿1号筷子但是1号筷子此时在B手中所以A会阻塞等待,此时E拿到5号筷子吃完后放下筷子->D拿到4号筷子吃完后放下筷子->C拿到3号筷子吃完后放下筷子->B拿到2号筷子吃完后放下筷子。
此时就完美避免了死锁问题的发生。文章来源地址https://www.toymoban.com/news/detail-753012.html

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

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

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

相关文章

  • 【Java EE 初阶】文件操作

    目录 1.什么是文件? 1.在cmd中查看指定目录的树形结构语法 2.文件路径 从当前目录开始找到目标程序(一个点) 返回到上一级目录,再找目标程序(两个点) 2.Java中文件操作 1.File概述 1.属性 2. 构造方法 3.常用方法  代码展示: 4.常用方法2 3. 文件内容的读写---数据流 1.I

    2024年02月06日
    浏览(43)
  • J2EE,Java EE,Jakarta EE 命名之间的恩恩怨怨

      简单来说,上面所有的名字指的都是一个东西 Java Platform, Enterprise Edition 上面的几个名词都是下面的内容的简写: J2EE(Java 2 Platform, Enterprise Edition) Java EE (Java Platform, Enterprise Edition) Jakarta EE(Jakarta Enterprise Edition) 上面的排序是按照时间演进来进行排序。   1998年12月,SUN公司发

    2023年04月26日
    浏览(44)
  • Java、Java EE、Spring和Spring Boot核心注解

    文章迁移至个人博客 此页面包含常用 Java 、 Java EE 、 Spring 、 Spring Boot 、 JPA 常用注解的一站式说明。 @Component注解 @Component 注解表明被注解的类是一个“spring bean/组件”。@Component注解告诉Spring容器自动创建Spring bean。 @Autowired注解 @Autowired 注解用于自动注入 bean。@Autowired 注

    2024年02月15日
    浏览(50)
  • 【Java EE初阶十三】网络初识

            网络发展的几个主要时期:         单机时代-局域网时代-广域网时代-移动互联网时代         随着时代的发展,越来越需要计算机之间互相通信,共享软件和数据,即以多个计算机协同工作来完成 业务,就有了网络互连。         网络互连: 将多台计

    2024年02月20日
    浏览(44)
  • 4.3Java EE——一对多查询

    用户与订单关联关系图 ​​​​​​​         与一对一的关联关系相比,接触更多的关联关系是一对多(或多对一)。例如一个用户可以有多个订单,多个订单也可以归一个用户所有。用户和订单的关联关系如图。 一、collection元素         在MyBatis中,通过collect

    2024年02月13日
    浏览(44)
  • 死锁(JAVA)

    死锁在多线程代码中是非常严重的BUG ,一旦代码中出现死锁就会导致线程卡死。 当 单个线程连续两次 对 同一个对象进行加锁 操作时,如果该锁是 不可重入锁 就会发生死锁(线程卡死) 两个线程两把锁,如果出现这种情况也是会发生死锁:线程t1已经获取了锁A,线程t2已

    2024年02月05日
    浏览(39)
  • JDK、JRE、Java SE、Java EE和Java ME有什么区别?

    Java现在已不仅仅是一种语言,从广义上说,它代表了一个技术体系。该体系根据应用方向的不同主要分为Java SE、Java EE和Java ME的3个部分。 1.SE(JavaSE),standard edition,标准版,是我们通常用的一个版本,从JDK 5.0开始,改名为Java SE。 2.EE(JavaEE),enterprise edition,个业版,使用这种

    2024年02月12日
    浏览(43)
  • 【Java EE】-博客系统一(前后端分离)

    作者 :学Java的冬瓜 博客主页 :☀冬瓜的主页🌙 专栏 :【JavaEE】 分享 : 谜一样的 沉默着的 故事你真的在听吗 ——《平凡之路》 主要内容 :准备工作:创建maven,引入依赖。设计数据库并编写数据库代码。前后端分离功能的实现。博客列表,博客详情,登录功能,注册功

    2024年02月12日
    浏览(43)
  • 【Java EE】-博客系统二(前后端分离)

    作者 :学Java的冬瓜 博客主页 :☀冬瓜的主页🌙 专栏 :【JavaEE】 分享 : 徘徊着的 在路上的 你要走吗 易碎的 骄傲着 那也曾是我的模样 ——《平凡之路》 主要内容 :显示用户信息、上传头像、新增博客、删除博客、修改博客。 分两个子功能:列表页显示登录用户信息;

    2024年02月11日
    浏览(43)
  • 【Java EE初阶十七】网络原理(二)

    2.2.2 关于可靠传输 4.滑动窗口         前面的三个机制,都是在保证 tcp 的可靠性;         TCP 的可靠传输,是会影响传输的效率的.(多出了一些等待 ack 的时间,单位时间内能传输的数据就少了);         滑动窗口,就让可靠传输对性能的影响,更少一些.TCP 只要引入了可

    2024年02月20日
    浏览(43)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包