返回顶部
首页 > 资讯 > 后端开发 > JAVA >Java中的死锁及其解决方案
  • 577
分享到

Java中的死锁及其解决方案

javaPoweredby金山文档 2023-09-04 09:09:20 577人浏览 安东尼
摘要

Java中的死锁及其解决方案 在Java中,锁是很常见的一个工具,常见的用法就是在高并发场景下保证线程安全,但是使用不当也会造成死锁,给我们带来一些不必要的麻烦,本文分析死锁及其产生原因,并作出相应的解决方案。 死锁产生的四个必要条件

Java中的死及其解决方案

在Java中,锁是很常见的一个工具,常见的用法就是在高并发场景下保证线程安全,但是使用不当也会造成死锁,给我们带来一些不必要的麻烦,本文分析死锁及其产生原因,并作出相应的解决方案。

死锁产生的四个必要条件

1)互斥条件:进程对所分配到的资源进行排他性控制,即在一段时间内某资源仅为一个进程所占有。此时若有其他进程请求该资源,则请求进程只能等待。

2)请求和保持条件:进程已经获得了至少一个资源,但又对其他资源发出请求,而该资源已被其他进程占有,此时该进程的请求被阻塞,但又对自己获得的资源保持不放。

3)不可剥夺条件:进程已获得的资源在未使用完毕之前,不可被其他进程强行剥夺,只能由自己释放。

4)环路等待条件:存在一种进程资源的循环等待链,链中每一个进程已获得的资源同时被 链中下一个进程所请求。

生活示例

死锁就好比两个人去过独木桥,小庞从桥左边出发,小贾从桥右边出发,然后到了桥中间,小庞要去右边,小贾要去左边,但两者都互不想让,最终只能在桥中间站着,造成死循环,谁也过不了河的结果。

对象A先持有锁1,然后对象B持有锁2,此时对象A要去获取锁2,但是锁2此时在对象B手里,对象B要去获取锁1,锁1在对象A手里,对象A,B互不相让,最终导致死链现象,出现死锁。

死锁代码

方式1,继承Runnable接口实现
package com.wwy.lock;import java.util.concurrent.TimeUnit;public class DieLock {    public static void main(String[] args) {         Object A = new Object();         Object B = new Object();         //线程1                Thread thread1 = new Thread(()->{            synchronized (A){                System.out.println("线程1此时获取锁A");                try {                                        TimeUnit.SECONDS.sleep(1);                } catch (InterruptedException e) {                    e.printStackTrace();                }                //对象A苏醒之后再去尝试获取锁2                synchronized (B){                    System.out.println("线程1此时获取锁B");                }            }        });        thread1.start();        //线程2        Thread thread2 = new Thread(()->{            synchronized (B){                System.out.println("线程2此时获取锁B");                try {                    TimeUnit.SECONDS.sleep(1);                } catch (InterruptedException e) {                    e.printStackTrace();                }                //对象A苏醒之后再去尝试获取锁2                synchronized (A){                    System.out.println("线程2此时获取锁A");                }            }        });        thread2.start();    }}

方式2,继承Thread类(不推荐使用)
package com.wwy.lock;import java.util.concurrent.TimeUnit;public class ThreadA extends Thread {    private Object A ;    private Object B ;    public Object getA() {        return A;    }    public void setA(Object a) {        A = a;    }    public Object getB() {        return B;    }    public void setB(Object b) {        B = b;    }    @Override    public void run() {        synchronized (A){            System.out.println("线程1此时获取锁A");            try {                TimeUnit.SECONDS.sleep(1);            } catch (InterruptedException e) {                e.printStackTrace();            }            synchronized (B){                System.out.println("线程1此时获取锁B");            }        }    }}
package com.wwy.lock;import java.util.concurrent.TimeUnit;public class ThreadB extends Thread {   private Object A ;   private Object B ;    public Object getA() {        return A;    }    public void setA(Object a) {        A = a;    }    public Object getB() {        return B;    }    public void setB(Object b) {        B = b;    }    @Override    public void run() {        synchronized (B){            System.out.println("线程2此时获取锁B");            try {                TimeUnit.SECONDS.sleep(1);            } catch (InterruptedException e) {                e.printStackTrace();            }            synchronized (A){                System.out.println("线程2此时获取锁A");            }        }    }}
package com.wwy.lock;public class ThreadTest  {    public static void main(String[] args) {        Object A = new Object();        Object B = new Object();        ThreadA t1 = new ThreadA();        ThreadB t2 = new ThreadB();        t1.setA(A);        t1.setB(B);        t2.setA(A);        t2.setB(B);        t1.start();        t2.start();    }}

检测死锁

正常情况下应该打印四句话的,可此时程序一直在运行状态并且只打印了两句话,说明出现死锁现象,验证方法,可以去到我们jdk目录下的bin目录中的一个可视化界面查看

可以看到此处确实出现死锁现象

死锁解决方案

预防死锁的方式就是打破四个必要条件中的任意一个即可。

1)打破互斥条件:在系统里取消互斥。若资源不被一个进程独占使用,那么死锁是肯定不会发生的。但一般来说在所列的四个条件中,“互斥”条件是无法破坏的。因此,在死锁预防里主要是破坏其他几个必要条件,而不去涉及破坏“互斥”条件。。

2)打破请求和保持条件:采用资源预先分配策略,即进程运行前申请全部资源,满足则运行,不然就等待。

每个进程提出新的资源申请前,必须先释放它先前所占有的资源。

3)打破不可剥夺条件:当进程占有某些资源后又进一步申请其他资源而无法满足,则该进程必须释放它原来占有的资源。

4)打破环路等待条件:实现资源有序分配策略,将系统的所有资源统一编号,所有进程只能采用按序号递增的形式申请资源。

方案一,改变两个线程获取锁的顺序

让线程1和线程2的获取锁的顺序都是先获取锁A在获取锁B

package com.wwy.lock;import java.util.concurrent.TimeUnit;public class DieLock {    public static void main(String[] args) {         Object A = new Object();         Object B = new Object();         //线程1                Thread thread1 = new Thread(()->{            synchronized (A){                System.out.println("线程1此时获取锁A");                try {                                        TimeUnit.SECONDS.sleep(1);                } catch (InterruptedException e) {                    e.printStackTrace();                }                //对象A苏醒之后再去尝试获取锁2                synchronized (B){                    System.out.println("线程1此时获取锁B");                }            }        });        thread1.start();        //线程2        Thread thread2 = new Thread(()->{            synchronized (A){                System.out.println("线程2此时获取锁A");                try {                    TimeUnit.SECONDS.sleep(1);                } catch (InterruptedException e) {                    e.printStackTrace();                }                //对象A苏醒之后再去尝试获取锁2                synchronized (B){                    System.out.println("线程2此时获取锁B");                }            }        });        thread2.start();    }}

继承Runnable类也是如此解决,改变两个线程获取锁的顺序

方式二,使用ReentrantLock来解决
package com.wwy.lock;import java.util.concurrent.TimeUnit;import java.util.concurrent.locks.ReentrantLock;public class DieLock {    public static void main(String[] args) {        ReentrantLock lockA = new ReentrantLock();        ReentrantLock lockB = new ReentrantLock();         //线程1                Thread thread1 = new Thread(()->{            while(true) {                if (lockA.tryLock()) {                    System.out.println("线程1获取锁A");                    try {                        TimeUnit.SECONDS.sleep(1);                        if (lockB.tryLock()) {try {    System.out.println("线程1获取锁B");} finally {    lockB.unlock();    System.out.println("线程1释放锁B");    break;}                        }                    } catch (InterruptedException e) {                        e.printStackTrace();                    } finally {                                                lockA.unlock();                        System.out.println("线程1释放锁A");                    }                }                try {                    TimeUnit.SECONDS.sleep(1);                } catch (InterruptedException e) {                    e.printStackTrace();                }            }        });        thread1.start();        //线程2        Thread thread2 = new Thread(()->{                        lockB.lock();                System.out.println("线程2获取锁B");                try {                    TimeUnit.SECONDS.sleep(1);                    lockA.lock();                        try {System.out.println("线程2获取锁A");                        }finally {lockA.unlock();System.out.println("线程2释放锁A");                        }                } catch (InterruptedException e) {                    e.printStackTrace();                }                finally {                                        lockB.unlock();                    System.out.println("线程2释放锁B");                }        });        thread2.start();    }}

来源地址:https://blog.csdn.net/weixin_45936627/article/details/129291519

--结束END--

本文标题: Java中的死锁及其解决方案

本文链接: https://lsjlt.com/news/393281.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Java中的死锁及其解决方案
    Java中的死锁及其解决方案 在Java中,锁是很常见的一个工具,常见的用法就是在高并发场景下保证线程安全,但是使用不当也会造成死锁,给我们带来一些不必要的麻烦,本文分析死锁及其产生原因,并作出相应的解决方案。 死锁产生的四个必要条件 ...
    99+
    2023-09-04
    java Powered by 金山文档
  • MySQL - 死锁的产生及解决方案
    MySQL - 死锁的产生及解决方案 1. 死锁与产生死锁的四个必要条件1.1 什么是死锁1.2 死锁产生的4个必要条件 2. 死锁案例2.1 表锁死锁2.2 行锁死锁2.3 共享锁转换为排他锁 3. 死锁排查4. 实例分析...
    99+
    2023-08-17
    mysql 数据库
  • Java 死锁解决方案顺序锁和轮询锁
    目录死锁解决方案分析解决方案1:顺序锁解决方案2:轮询锁总结前言: 死锁(Dead Lock)指的是两个或两个以上的运算单元(进程、线程或协程),都在等待对方停止执行,以取得系统资源...
    99+
    2024-04-02
  • mysql出现死锁的原因及解决方案
    本文主要给大家介绍mysql出现死锁的原因及解决方案,文章内容都是笔者用心摘选和编辑的,具有一定的针对性,对大家的参考意义还是比较大的,下面跟笔者一起了解下mysql出现死锁的原因及解决方案吧。mysql都...
    99+
    2024-04-02
  • 常见的MySQL锁问题及其解决方案
    MySQL 锁的常见问题与解决方案MySQL 是一种常用的关系型数据库管理系统,它使用锁来实现并发控制,保证数据的一致性和完整性。然而,MySQL 锁的使用也会带来一些问题。本文将介绍一些常见的 MySQL 锁的问题,并提供相应的解决方案。...
    99+
    2023-12-21
    解决方案 常见问题 MySQL
  • MySQL死锁的产生原因以及解决方案
    数据库和操作系统一样,是一个多用户使用的共享资源。当多个用户并发地存取数据 时,在数据库中就会产生多个事务同时存取同一数据的情况。若对并发操作不加控制就可能会读取和存储不正确的数据,破坏数据库的一致性。加锁是实现数据...
    99+
    2022-05-15
    MySQL 死锁 MySQL 死锁解决
  • 关于Process的waitFor死锁问题及解决方案
    目录Process的waitFor死锁问题1、发现问题2、原因查找3、造成死锁原理图问题代码解决方案Java中死锁的简单例子及其避免我们来看一个死锁的简单例子那么要怎么预防死锁呢?P...
    99+
    2024-04-02
  • 【mysql】mysql死锁问题解决方案
    mysql死锁问题解决方案 查询出是被哪个进程给锁住了为什么会产生死锁日志内容:日志解析:找到问题: 解决方案 查询出是被哪个进程给锁住了 执行sql: select ...
    99+
    2023-09-23
    mysql adb 数据库
  • MySQL死锁的原因及解决方法
    这篇文章主要介绍“MySQL死锁的原因及解决方法”,在日常操作中,相信很多人在MySQL死锁的原因及解决方法问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”MySQL死锁的原因...
    99+
    2024-04-02
  • 死锁之谜:探究数据库死锁的原因和解决方案
    数据库死锁是指两个或多个事务在同时执行过程中,由于互相等待对方释放锁而导致无限期等待的情况。这会导致事务无法继续执行,进而影响数据库的性能和可用性。 1. 数据库死锁的原因 数据库死锁通常是由以下原因引起的: 资源竞争: 当两个或多个...
    99+
    2024-02-05
    数据库死锁 事务 死锁检测 死锁预防 死锁恢复
  • java解决死锁的方法有哪些
    在Java中,可以采用以下方法解决死锁问题:1. 避免(Avoidance):避免使用多个锁,或者按照相同的顺序获取锁,以避免发生死...
    99+
    2023-08-08
    java
  • 数据库死锁产生的原因及解决方案有哪些
    数据库死锁产生的原因及解决方案有哪些?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。数据库死锁产生的原因及解决方案:1、程序的B...
    99+
    2024-04-02
  • 如何解决java中的死锁问题
    一、死锁的定义死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。那么我们换一个更加规范的定义:集合中的每一个进程都在等待只能由本集合中的其他进程才能引发的事件,...
    99+
    2016-01-19
    java教程 java 死锁
  • java并发编程死锁定义及避免死锁案例分析
    这篇文章主要介绍“java并发编程死锁定义及避免死锁案例分析”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“java并发编程死锁定义及避免死锁案例分析”文章能帮助大家解决问题。场景模拟分析场景一:狭路...
    99+
    2023-06-29
  • MySQL死锁问题的分析及解决方法
    这篇文章主要讲解了“MySQL死锁问题的分析及解决方法”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“MySQL死锁问题的分析及解决方法”吧!MySQL死锁问...
    99+
    2024-04-02
  • 解决MySQL死锁的方法
    下面一起来了解下解决MySQL死锁的方法,相信大家看完肯定会受益匪浅,文字在精不在多,希望解决MySQL死锁的方法这篇短内容是你想要的。 一、查看MySQL死锁MySQL数据库会自己解决死锁,ki...
    99+
    2024-04-02
  • mysql死锁的解决方法
    mysql死锁的解决方法?这个问题可能是我们日常学习或工作经常见到的。希望通过这个问题能让你收获颇深。下面是小编给大家带来的参考内容,让我们一起来看看吧!MySQL有两种死锁处理方式:● 等待,直到超时(i...
    99+
    2024-04-02
  • Java多线程死锁如何避免及解决
    本篇内容介绍了“Java多线程死锁如何避免及解决”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!下面是一个多线程死锁的例子输出thread1&...
    99+
    2023-06-02
  • mysql死锁介绍以及解决
    什么是死锁 死锁是2+个线程在执行过程中, 因争夺资源而造成的相互等待的现象,若无外力作用,它们将无法推进下去。 死锁产生的4个必要条件 互斥条件 指进程对所分配的资源进行排他性使用,即一段时间内某资源只有一个进程占用,其他的进程请求资源只...
    99+
    2023-08-17
    mysql java 微服务
  • sql死锁的原因及解决方法是什么
    SQL死锁是指在多个并发事务中,每个事务都在等待其他事务所持有的资源,导致所有事务都无法继续执行的状态。死锁的原因主要有以下几种:1...
    99+
    2023-08-16
    sql
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作