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

news/2024/7/8 6:10:22

目录

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 的锁");
                }
            }
        }
    }


}

一直等待下了。。。

 去找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内容的最后:

可以清晰的看到:

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

避免死锁的几个常见方法

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

参考:【JVM】面试题之死锁及问题是怎么定位_jvm线程锁定定位_it噩梦的博客-CSDN博客


http://lihuaxi.xjx100.cn/news/1026358.html

相关文章

URLEncode原理(全网详解)

概念&#xff1a; URLEncode是一种将特殊字符转换成百分号编码的方法&#xff0c;以便浏览器和服务器之间能够正确地处理它们。该方法会将某些字符替换为由 % 和其后面的两个十六进制数字所组成的编码。这些字符包括字母、数字、下划线、连字符、句点以及某些保留字符。 URLE…

基于亚马逊云科技无服务器架构,开发者可以有效实现快速上线

开发一个“爆款”游戏总共需要几步&#xff1f;Marvel Snap可能会告诉你&#xff1a;第一步&#xff0c;专心致志把游戏做好、提高可玩性&#xff1b;第二步&#xff0c;把其他工作交给亚马逊云科技。 相关数据显示&#xff0c;自2022年10月18日正式发行以来&#xff0c;在不到…

有学生问我,重构是什么?我应该如何回答?

重构到底是什么&#xff1f;只是代码的推倒重新编码&#xff1f;还是有规则、有方法可寻&#xff1f;当然&#xff0c;结论肯定是有的&#xff0c;本文&#xff0c;我们通过一个简单的实例&#xff0c;来理解一下重构。 1.借助一个实例需求 这是一个影片出租店用的程序&#…

OpenAI-ChatGPT最新官方接口《文本交互》全网最详细中英文实用指南和教程,助你零基础快速轻松掌握全新技术(一)(附源码)

Text completion 文本交互前言Introduction 导言Prompt design 提示设计Basics基础知识TroubleshootingClassificationImproving the classifiers efficiency 提高分类器的效率Generation 总结Conversation 对话Transformation 变化Translation 翻译Conversion 转化Summarizati…

【分布式应用】Zabbix——安装

目录 第一章zabbix概述 1.1.什么是监控概念 1.2.zabbix概述 1.3.zabbix 主要特点 1.4.zabbix主要功能 1.5.zabbix运行机制 1.6.zabbix 监控原理 1.7zabbix的架构&#xff0c;数据流向以及原理在图中做总结 1.8.数据采集模式 1.9.zabbix监控模式 第二章.安装 部署 za…

李宏毅教程系列——增强学习

目录 0. 强化学习wiki 1. 介绍 2. Exploration vs Exploitation 探索与开发 3. 各类最优化方法 3.1 Brute force猛兽蛮力法&#xff08;暴力搜索&#xff09; 3.2 Value function estimation&#xff08;价值函数估计&#xff09; 3.2.1 Monte Carlo methods 蒙特卡洛方…

苹果AirPods耳机推送新固件更新,TWS耳机与Find My可实现智能防丢

苹果推送 iOS / iPadOS 16.5 Beta 2 更新的同时&#xff0c;原本还为 AirPods 耳机推送了固件更新 5E133。苹果在临时撤回之后&#xff0c;再次向用户推送了本次更新&#xff0c; 苹果官方表示当你的 AirPods 在充电且在 iPhone、iPad 或 Mac 的蓝牙通信范围内时&#xff0c;…

JavaScript对象类型之Array及Object

目录 一、Array &#xff08;1&#xff09;语法 &#xff08;2&#xff09;API 二、Object &#xff08;1&#xff09;语法 &#xff08;2&#xff09;特色&#xff1a;属性增删 &#xff08;3&#xff09;特色&#xff1a;this &#xff08;4&#xff09;特色&#xf…