Java避免死锁的几个常见方法(有测试代码和分析过程)

这篇具有很好参考价值的文章主要介绍了Java避免死锁的几个常见方法(有测试代码和分析过程)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

Java避免死锁的几个常见方法

死锁产生的条件

上死锁代码

然后 :jstack 14320 >> jstack.text

Java避免死锁的几个常见方法


Java避免死锁的几个常见方法

  • 避免一个线程同时获取多个锁。
  • 避免一个线程在锁内同时占用多个资源,尽量保证每个锁只占用一个资源。
  • 尝试使用定时锁,使用lock.tryLock(timeout)来替代使用内部锁机制。
  • 对于数据库锁,加锁和解锁必须在一个数据库连接里,否则会出现解锁失败的情况。

死锁产生的条件

  1. 互斥条件:进程对所分配到的资源不允许其他进程进行访问,若其他进程访问该资源,只能等待,直至占有该资源的进程使用完成后释放该资源
  2. 请求和保持条件:进程获得一定的资源之后,又对其他资源发出请求,但是该资源可能被其他进程占有,此事请求阻塞,但又对自己获得的资源保持不放
  3. 不可剥夺条件:是指进程已获得的资源,在未完成使用之前,不可被剥夺,只能在使用完后自己释放
  4. 环路等待条件:是指进程发生死锁后,必然存在一个进程–资源之间的环形链死锁问题

上死锁代码

package cn.net.cdsz.ccb.test;

public class TestDeadLock {

    private static Object obj1 = new Object();
    private static Object obj2 = new Object();

    public static void main(String[] args) {
        new Thread(new Thread1()).start();
        new Thread(new Thread2()).start();
    }

    private static class Thread1 implements Runnable {
        @Override
        public void run() {
            synchronized (obj1) {
                System.out.println("Thread1 拿到 obj1 的锁");
                try {
                    //停顿2秒的意义在于,让thread2线程拿到obj2的锁
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                synchronized (obj2) {
                    System.out.println("Thread1 拿到 obj2 的锁");
                }
            }

        }
    }

    private static class Thread2 implements Runnable {
        @Override
        public void run() {
            synchronized (obj2) {
                System.out.println("Thread2 拿到 obj2 的锁");
                try {
                    //停顿2秒的意义在于,让thread1线程拿到obj1的锁
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                synchronized (obj1) {
                    System.out.println("Thread2 拿到 obj1 的锁");
                }
            }
        }
    }


}

Java避免死锁的几个常见方法(有测试代码和分析过程)

一直等待下了。。。

Java避免死锁的几个常见方法(有测试代码和分析过程)

 去找pid:14320

然后 :jstack 14320 >> jstack.text

得到以下内容:

2023-04-14 14:51:33
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.31-b07 mixed mode):

"JMX server connection timeout 21" #21 daemon prio=5 os_prio=0 tid=0x000000002167d800 nid=0x6108 in Object.wait() [0x00000000225ef000]
   java.lang.Thread.State: TIMED_WAITING (on object monitor)
	at java.lang.Object.wait(Native Method)
	at com.sun.jmx.remote.internal.ServerCommunicatorAdmin$Timeout.run(ServerCommunicatorAdmin.java:168)
	- locked <0x000000076e3b32b8> (a [I)
	at java.lang.Thread.run(Thread.java:745)

"RMI Scheduler(0)" #20 daemon prio=5 os_prio=0 tid=0x0000000021674800 nid=0x3d78 waiting on condition [0x00000000224ee000]
   java.lang.Thread.State: TIMED_WAITING (parking)
	at sun.misc.Unsafe.park(Native Method)
	- parking to wait for  <0x000000076dc34d08> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
	at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2078)
	at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1093)
	at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:809)
	at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at java.lang.Thread.run(Thread.java:745)

"RMI TCP Connection(1)-192.168.136.113" #19 daemon prio=5 os_prio=0 tid=0x0000000021a3b800 nid=0x10c0 runnable [0x00000000223ee000]
   java.lang.Thread.State: RUNNABLE
	at java.net.SocketInputStream.socketRead0(Native Method)
	at java.net.SocketInputStream.read(SocketInputStream.java:150)
	at java.net.SocketInputStream.read(SocketInputStream.java:121)
	at java.io.BufferedInputStream.fill(BufferedInputStream.java:246)
	at java.io.BufferedInputStream.read(BufferedInputStream.java:265)
	- locked <0x000000076e281978> (a java.io.BufferedInputStream)
	at java.io.FilterInputStream.read(FilterInputStream.java:83)
	at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:550)
	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:826)
	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$240(TCPTransport.java:683)
	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler$$Lambda$1/410101441.run(Unknown Source)
	at java.security.AccessController.doPrivileged(Native Method)
	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:682)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at java.lang.Thread.run(Thread.java:745)

"RMI TCP Accept-0" #18 daemon prio=5 os_prio=0 tid=0x00000000212dc000 nid=0x8584 runnable [0x000000000153e000]
   java.lang.Thread.State: RUNNABLE
	at java.net.DualStackPlainSocketImpl.accept0(Native Method)
	at java.net.DualStackPlainSocketImpl.socketAccept(DualStackPlainSocketImpl.java:131)
	at java.net.AbstractPlainSocketImpl.accept(AbstractPlainSocketImpl.java:404)
	at java.net.PlainSocketImpl.accept(PlainSocketImpl.java:199)
	- locked <0x000000076dc69d98> (a java.net.SocksSocketImpl)
	at java.net.ServerSocket.implAccept(ServerSocket.java:545)
	at java.net.ServerSocket.accept(ServerSocket.java:513)
	at sun.management.jmxremote.LocalRMIServerSocketFactory$1.accept(LocalRMIServerSocketFactory.java:52)
	at sun.rmi.transport.tcp.TCPTransport$AcceptLoop.executeAcceptLoop(TCPTransport.java:400)
	at sun.rmi.transport.tcp.TCPTransport$AcceptLoop.run(TCPTransport.java:372)
	at java.lang.Thread.run(Thread.java:745)

"DestroyJavaVM" #16 prio=5 os_prio=0 tid=0x000000000365b000 nid=0xae0 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Thread-1" #15 prio=5 os_prio=0 tid=0x000000001ec17000 nid=0x69ac waiting for monitor entry [0x0000000020a1f000]
   java.lang.Thread.State: BLOCKED (on object monitor)
	at cn.net.cdsz.ccb.test.TestDeadLock$Thread2.run(TestDeadLock.java:46)
	- waiting to lock <0x000000076c88add0> (a java.lang.Object)
	- locked <0x000000076c88ade0> (a java.lang.Object)
	at java.lang.Thread.run(Thread.java:745)

"Thread-0" #14 prio=5 os_prio=0 tid=0x000000001ec24800 nid=0x8d08 waiting for monitor entry [0x000000002091f000]
   java.lang.Thread.State: BLOCKED (on object monitor)
	at cn.net.cdsz.ccb.test.TestDeadLock$Thread1.run(TestDeadLock.java:26)
	- waiting to lock <0x000000076c88ade0> (a java.lang.Object)
	- locked <0x000000076c88add0> (a java.lang.Object)
	at java.lang.Thread.run(Thread.java:745)

"Service Thread" #13 daemon prio=9 os_prio=0 tid=0x000000001eb16000 nid=0x8ac8 runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C1 CompilerThread3" #12 daemon prio=9 os_prio=2 tid=0x000000001ea92800 nid=0x67b4 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C2 CompilerThread2" #11 daemon prio=9 os_prio=2 tid=0x000000001ea8f800 nid=0x5c68 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C2 CompilerThread1" #10 daemon prio=9 os_prio=2 tid=0x000000001ea8f000 nid=0x6b4c waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C2 CompilerThread0" #9 daemon prio=9 os_prio=2 tid=0x000000001ea8d800 nid=0x7974 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"JDWP Command Reader" #8 daemon prio=10 os_prio=0 tid=0x000000001ea53800 nid=0x3634 runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"JDWP Event Helper Thread" #7 daemon prio=10 os_prio=0 tid=0x000000001ea4d800 nid=0x86e0 runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"JDWP Transport Listener: dt_socket" #6 daemon prio=10 os_prio=0 tid=0x000000001ea41000 nid=0x540 runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Attach Listener" #5 daemon prio=5 os_prio=2 tid=0x000000001e9e6000 nid=0x83a0 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Signal Dispatcher" #4 daemon prio=9 os_prio=2 tid=0x000000001e9e5000 nid=0x8dec runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Finalizer" #3 daemon prio=8 os_prio=1 tid=0x000000001d2eb800 nid=0x8670 in Object.wait() [0x000000001fd1f000]
   java.lang.Thread.State: WAITING (on object monitor)
	at java.lang.Object.wait(Native Method)
	- waiting on <0x000000076c3862f8> (a java.lang.ref.ReferenceQueue$Lock)
	at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:142)
	- locked <0x000000076c3862f8> (a java.lang.ref.ReferenceQueue$Lock)
	at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:158)
	at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:209)

"Reference Handler" #2 daemon prio=10 os_prio=2 tid=0x000000001d2ea000 nid=0x8ba4 in Object.wait() [0x000000001fc1e000]
   java.lang.Thread.State: WAITING (on object monitor)
	at java.lang.Object.wait(Native Method)
	- waiting on <0x000000076c385d68> (a java.lang.ref.Reference$Lock)
	at java.lang.Object.wait(Object.java:502)
	at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:157)
	- locked <0x000000076c385d68> (a java.lang.ref.Reference$Lock)

"VM Thread" os_prio=2 tid=0x000000001e9a1800 nid=0x6398 runnable 

"GC task thread#0 (ParallelGC)" os_prio=0 tid=0x0000000003670000 nid=0x7e64 runnable 

"GC task thread#1 (ParallelGC)" os_prio=0 tid=0x0000000003671800 nid=0x8218 runnable 

"GC task thread#2 (ParallelGC)" os_prio=0 tid=0x0000000003673000 nid=0x7830 runnable 

"GC task thread#3 (ParallelGC)" os_prio=0 tid=0x0000000003674800 nid=0x8e8c runnable 

"GC task thread#4 (ParallelGC)" os_prio=0 tid=0x0000000003676800 nid=0x8114 runnable 

"GC task thread#5 (ParallelGC)" os_prio=0 tid=0x0000000003678000 nid=0x8220 runnable 

"GC task thread#6 (ParallelGC)" os_prio=0 tid=0x000000000367b000 nid=0x6fc0 runnable 

"GC task thread#7 (ParallelGC)" os_prio=0 tid=0x000000000367c000 nid=0x26d8 runnable 

"GC task thread#8 (ParallelGC)" os_prio=0 tid=0x000000000367d800 nid=0x8238 runnable 

"GC task thread#9 (ParallelGC)" os_prio=0 tid=0x000000000367e800 nid=0x82a4 runnable 

"VM Periodic Task Thread" os_prio=2 tid=0x000000001eb18000 nid=0x8900 waiting on condition 

JNI global references: 4894


Found one Java-level deadlock:
=============================
"Thread-1":
  waiting to lock monitor 0x000000001d2f21b8 (object 0x000000076c88add0, a java.lang.Object),
  which is held by "Thread-0"
"Thread-0":
  waiting to lock monitor 0x000000001d2ef668 (object 0x000000076c88ade0, a java.lang.Object),
  which is held by "Thread-1"

Java stack information for the threads listed above:
===================================================
"Thread-1":
	at cn.net.cdsz.ccb.test.TestDeadLock$Thread2.run(TestDeadLock.java:46)
	- waiting to lock <0x000000076c88add0> (a java.lang.Object)
	- locked <0x000000076c88ade0> (a java.lang.Object)
	at java.lang.Thread.run(Thread.java:745)
"Thread-0":
	at cn.net.cdsz.ccb.test.TestDeadLock$Thread1.run(TestDeadLock.java:26)
	- waiting to lock <0x000000076c88ade0> (a java.lang.Object)
	- locked <0x000000076c88add0> (a java.lang.Object)
	at java.lang.Thread.run(Thread.java:745)

Found 1 deadlock.

以上jstack.text内容的最后:

Java避免死锁的几个常见方法(有测试代码和分析过程)

可以清晰的看到:

Thread-1获取了 <0x000000076c88ade0> 的锁,等待获取 <0x000000076c88add0> 这个锁
Thread-0获取了 <0x000000076c88add0> 的锁,等待获取 <0x000000076c88ade0> 这个锁
由此可见,发生了死锁。
 

避免死锁的几个常见方法

  • 避免一个线程同时获取多个锁。
  • 避免一个线程在锁内同时占用多个资源,尽量保证每个锁只占用一个资源。
  • 尝试使用定时锁,使用lock.tryLock(timeout)来替代使用内部锁机制。
  • 对于数据库锁,加锁和解锁必须在一个数据库连接里,否则会出现解锁失败的情况。

参考:【JVM】面试题之死锁及问题是怎么定位_jvm线程锁定定位_it噩梦的博客-CSDN博客文章来源地址https://www.toymoban.com/news/detail-415114.html

到了这里,关于Java避免死锁的几个常见方法(有测试代码和分析过程)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • 背会了常见的几个线程池用法,结果被问翻了

    分享是最有效的学习方式。 这是张小帅失业之后的第三场面试。 面试官:“实际开发中用过多线程吧,那聊聊线程池吧”。 “有CachedThreadPool:可缓存线程池,FixedThreadPool:定长线程池.......balabala”。小帅暗暗窃喜,还好把这几种线程池背下来了,看来这次可以上岸了。 面试官

    2024年02月02日
    浏览(67)
  • 连接贝尔金无线路由器时需要注意的几个常见问题

        一、随着使用无线设备连接无线网的情况越来越多,同时涌现出越来越多的无线网络问题,针对个人设备的网络访问控制、为移动访问建立限制和政策、外界干扰对无线网络的影响、无线网络安全以及移动设备数据监督等。 二、不过好在还可以支持客户部署新的无线网络

    2024年02月05日
    浏览(58)
  • API接口测试工具的几个特色

    API接口测试工具在软件开发过程中起着举足轻重的作用。它们帮助测试人员快速发现和解决API接口的问题,并确保系统的稳定性和性能。本文将介绍API接口测试工具的几个特色,以及为什么它们对测试人员来说非常重要。   首先,API接口测试工具的一个特色是它们能够发送和

    2024年02月15日
    浏览(44)
  • 关于AMC8模拟考试延长到1月19日14点,以及常见的几个新问题

    相信过去的周末两天,很多参加今年AMC8美国数学思维竞赛活动的孩子们都参加了AMC8模拟考试。昨天有家长问六分成长,周末两天因故没能参加要不要紧?如果还想参加怎么办? 不用担心!官方已经把AMC8模拟考试的时间延长到1月19日(星期五)14点了,也就是正式比赛当天下

    2024年01月19日
    浏览(79)
  • SQL调优的几个方法

    1.为什么调优,好处是什么?  SQL语句在编写之后,对于数据量较少的表基本没有什么性能上的需求,但是如果考虑到性能方面的话,SQL语句优化就是必须的。 2.如何调优?调有点方法有哪些?   1、对查询进行优化,应尽量避免全表扫描,首先考虑在where及order by上建立索引

    2024年02月16日
    浏览(41)
  • C#代码重构的几个典型案例

    前段时间小编检查同事代码,发现居然写的太复杂看不太懂,代码命名不规范,重复冗长代码一堆,这时候就可以通过重构来改进代码的质量。代码重构是提高代码质量和可维护性的关键过程,它旨在通过优化代码结构和设计来提高代码的可读性、可理解性和可扩展性。本文

    2024年02月16日
    浏览(33)
  • Linux分析内存占用的几个方法

    内存管理是一个非常重要的任务,Linux内存占用分析的方法不只以上几种,用户可以根据需要选择合适的方法进行使用。对于使用Linux进行开发和运维的人员,熟练使用这些命令和方法能够帮助他们更好的管理系统资源,提高系统性能和稳定性。 1. free命令 free命令可以查看L

    2024年02月13日
    浏览(53)
  • word转Markdown文件的几个方法

    word转Markdown文件的几个方法 1、 安装writage 软件,但是writage 需要收费了。 如果只是markdown文本编辑,可以直接安装typora来。 2. 利用Pandoc软件来转换word文件到markdown文件 注意doc文件需要保存docx文件格式才可以使用下面命令行

    2024年02月13日
    浏览(31)
  • 操作系统考试复习——第三章 预防死锁 避免死锁

    预防死锁: 就是破坏死锁产生的四个条件之一就行。 0.破坏互斥条件:由于互斥条件是非共享设备所必须的所以,不仅不能改变还需要保证。因此我们主要考虑剩下的三个条件。 1. 破坏 \\\"请求和保持\\\" 条件 请求和保持也就是系统已经请求了一个资源它现在占有这个资源但是它

    2024年02月03日
    浏览(44)
  • Java中ElasticSearch的几个简单查询

    1 term查询 单值查询,代表完全匹配,类似于mysql中的 = 。在搜索前不会对进行分词,直接去文档分词库匹配。筛选出一个字段等于特定值的所有记录。 会对查询结果进行打分(score),分值越高的数据排名越靠前。 在SQL中:  ES中的查询有很大差别,它把sql中的一条数

    2024年02月06日
    浏览(38)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包