Java多线程死锁案例 落日映苍穹つ 2021-12-20 04:09 309阅读 0赞 ## 产生死锁的原因 ## 就是,两个线程互相等待着对象释放锁,一直这样僵持下去,所以导致了死锁的产生,下面这个代码就会产生一个死锁: package com.example.demo.thread; public class DeadLockDemo { private static String A = "A"; private static String B = "B"; public static void main(String[] args) { new DeadLockDemo().deadLock(); } private void deadLock() { Thread t1 = new Thread(() -> { synchronized (A){ try { Thread.sleep(2000); }catch (InterruptedException e){ e.printStackTrace(); } synchronized (B){ System.out.println("1"); } } }); Thread t2 = new Thread(()->{ synchronized (B){ synchronized (A){ System.out.println("2"); } } }); t1.start(); t2.start(); } } 代码来源于《Java并发编程艺术之美》,当我运行了该程序后,一直没有输出,采用visualVM工具来进行诊断,结果如下图所示: ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTI5MzQzMjU_size_16_color_FFFFFF_t_70] 从该图中,我们可以看出,`DeadLockDemo`类的线程的`pid=6428`,,可以看到红色框中提示,有死锁存在。 然后点击右上角的`Thread Dump`文件,来分析一下该文件的内容,具体内容如下: 2019-06-28 21:11:20 Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.211-b12 mixed mode): "RMI TCP Connection(2)-10.2.4.117" #19 daemon prio=5 os_prio=0 tid=0x000000001c6c2800 nid=0x442c runnable [0x000000001dc6d000] java.lang.Thread.State: RUNNABLE at java.net.SocketInputStream.socketRead0(Native Method) at java.net.SocketInputStream.socketRead(SocketInputStream.java:116) at java.net.SocketInputStream.read(SocketInputStream.java:171) at java.net.SocketInputStream.read(SocketInputStream.java:141) at java.io.BufferedInputStream.fill(BufferedInputStream.java:246) at java.io.BufferedInputStream.read(BufferedInputStream.java:265) - locked <0x0000000781963ed0> (a java.io.BufferedInputStream) at java.io.FilterInputStream.read(FilterInputStream.java:83) at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:555) at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:834) at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:688) at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler$$Lambda$5/904339139.run(Unknown Source) at java.security.AccessController.doPrivileged(Native Method) at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:687) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at java.lang.Thread.run(Thread.java:748) Locked ownable synchronizers: - <0x0000000781599378> (a java.util.concurrent.ThreadPoolExecutor$Worker) "JMX server connection timeout 18" #18 daemon prio=5 os_prio=0 tid=0x000000001c639800 nid=0x1f64 in Object.wait() [0x000000001db6f000] java.lang.Thread.State: TIMED_WAITING (on object monitor) at java.lang.Object.wait(Native Method) - waiting on <0x0000000781703b78> (a [I) at com.sun.jmx.remote.internal.ServerCommunicatorAdmin$Timeout.run(ServerCommunicatorAdmin.java:168) - locked <0x0000000781703b78> (a [I) at java.lang.Thread.run(Thread.java:748) Locked ownable synchronizers: - None "RMI Scheduler(0)" #17 daemon prio=5 os_prio=0 tid=0x000000001c638800 nid=0x305c waiting on condition [0x000000001da6f000] java.lang.Thread.State: TIMED_WAITING (parking) at sun.misc.Unsafe.park(Native Method) - parking to wait for <0x00000007814abc08> (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:1074) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at java.lang.Thread.run(Thread.java:748) Locked ownable synchronizers: - None "RMI TCP Connection(1)-10.2.4.117" #16 daemon prio=5 os_prio=0 tid=0x000000001bd25800 nid=0x389c runnable [0x000000001d96d000] java.lang.Thread.State: RUNNABLE at java.net.SocketInputStream.socketRead0(Native Method) at java.net.SocketInputStream.socketRead(SocketInputStream.java:116) at java.net.SocketInputStream.read(SocketInputStream.java:171) at java.net.SocketInputStream.read(SocketInputStream.java:141) at java.io.BufferedInputStream.fill(BufferedInputStream.java:246) at java.io.BufferedInputStream.read(BufferedInputStream.java:265) - locked <0x00000007816892c0> (a java.io.BufferedInputStream) at java.io.FilterInputStream.read(FilterInputStream.java:83) at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:555) at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:834) at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:688) at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler$$Lambda$5/904339139.run(Unknown Source) at java.security.AccessController.doPrivileged(Native Method) at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:687) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at java.lang.Thread.run(Thread.java:748) Locked ownable synchronizers: - <0x0000000781594850> (a java.util.concurrent.ThreadPoolExecutor$Worker) "RMI TCP Accept-0" #15 daemon prio=5 os_prio=0 tid=0x000000001bcdc000 nid=0x2674 runnable [0x000000001d76e000] 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:409) at java.net.PlainSocketImpl.accept(PlainSocketImpl.java:199) - locked <0x00000007814bd318> (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:405) at sun.rmi.transport.tcp.TCPTransport$AcceptLoop.run(TCPTransport.java:377) at java.lang.Thread.run(Thread.java:748) Locked ownable synchronizers: - None "DestroyJavaVM" #13 prio=5 os_prio=0 tid=0x0000000003454000 nid=0x2f28 waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE Locked ownable synchronizers: - None "Thread-1" #12 prio=5 os_prio=0 tid=0x000000001c654800 nid=0x42e8 waiting for monitor entry [0x000000001cf4f000] java.lang.Thread.State: BLOCKED (on object monitor) at com.example.demo.thread.DeadLockDemo.lambda$deadLock$1(DeadLockDemo.java:27) - waiting to lock <0x0000000780ae7e30> (a java.lang.String) - locked <0x0000000780ae7e60> (a java.lang.String) at com.example.demo.thread.DeadLockDemo$$Lambda$2/2128227771.run(Unknown Source) at java.lang.Thread.run(Thread.java:748) Locked ownable synchronizers: - None "Thread-0" #11 prio=5 os_prio=0 tid=0x000000001c652000 nid=0x22d4 waiting for monitor entry [0x000000001ce4e000] java.lang.Thread.State: BLOCKED (on object monitor) at com.example.demo.thread.DeadLockDemo.lambda$deadLock$0(DeadLockDemo.java:20) - waiting to lock <0x0000000780ae7e60> (a java.lang.String) - locked <0x0000000780ae7e30> (a java.lang.String) at com.example.demo.thread.DeadLockDemo$$Lambda$1/2121055098.run(Unknown Source) at java.lang.Thread.run(Thread.java:748) Locked ownable synchronizers: - None "Service Thread" #10 daemon prio=9 os_prio=0 tid=0x000000001bbd3800 nid=0x3654 runnable [0x0000000000000000] java.lang.Thread.State: RUNNABLE Locked ownable synchronizers: - None "C1 CompilerThread2" #9 daemon prio=9 os_prio=2 tid=0x000000001bb51000 nid=0x3020 waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE Locked ownable synchronizers: - None "C2 CompilerThread1" #8 daemon prio=9 os_prio=2 tid=0x000000001bb45800 nid=0x4050 waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE Locked ownable synchronizers: - None "C2 CompilerThread0" #7 daemon prio=9 os_prio=2 tid=0x000000001bb44800 nid=0x4634 waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE Locked ownable synchronizers: - None "Monitor Ctrl-Break" #6 daemon prio=5 os_prio=0 tid=0x000000001bb26800 nid=0x43b8 runnable [0x000000001c02e000] java.lang.Thread.State: RUNNABLE at java.net.SocketInputStream.socketRead0(Native Method) at java.net.SocketInputStream.socketRead(SocketInputStream.java:116) at java.net.SocketInputStream.read(SocketInputStream.java:171) at java.net.SocketInputStream.read(SocketInputStream.java:141) at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284) at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326) at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178) - locked <0x0000000780b2bb38> (a java.io.InputStreamReader) at java.io.InputStreamReader.read(InputStreamReader.java:184) at java.io.BufferedReader.fill(BufferedReader.java:161) at java.io.BufferedReader.readLine(BufferedReader.java:324) - locked <0x0000000780b2bb38> (a java.io.InputStreamReader) at java.io.BufferedReader.readLine(BufferedReader.java:389) at com.intellij.rt.execution.application.AppMainV2$1.run(AppMainV2.java:64) Locked ownable synchronizers: - None "Attach Listener" #5 daemon prio=5 os_prio=2 tid=0x000000001b93b800 nid=0x5dc waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE Locked ownable synchronizers: - None "Signal Dispatcher" #4 daemon prio=9 os_prio=2 tid=0x000000001a63e800 nid=0x4770 runnable [0x0000000000000000] java.lang.Thread.State: RUNNABLE Locked ownable synchronizers: - None "Finalizer" #3 daemon prio=8 os_prio=1 tid=0x000000000354e000 nid=0x3fdc in Object.wait() [0x000000001b92f000] java.lang.Thread.State: WAITING (on object monitor) at java.lang.Object.wait(Native Method) - waiting on <0x0000000780908ed0> (a java.lang.ref.ReferenceQueue$Lock) at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:144) - locked <0x0000000780908ed0> (a java.lang.ref.ReferenceQueue$Lock) at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:165) at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:216) Locked ownable synchronizers: - None "Reference Handler" #2 daemon prio=10 os_prio=2 tid=0x000000001a5ca800 nid=0x1b38 in Object.wait() [0x000000001b82f000] java.lang.Thread.State: WAITING (on object monitor) at java.lang.Object.wait(Native Method) - waiting on <0x0000000780906bf8> (a java.lang.ref.Reference$Lock) at java.lang.Object.wait(Object.java:502) at java.lang.ref.Reference.tryHandlePending(Reference.java:191) - locked <0x0000000780906bf8> (a java.lang.ref.Reference$Lock) at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153) Locked ownable synchronizers: - None "VM Thread" os_prio=2 tid=0x000000001a5a7000 nid=0x3b50 runnable "GC task thread#0 (ParallelGC)" os_prio=0 tid=0x000000000346a800 nid=0x4698 runnable "GC task thread#1 (ParallelGC)" os_prio=0 tid=0x000000000346c000 nid=0x4048 runnable "GC task thread#2 (ParallelGC)" os_prio=0 tid=0x000000000346d800 nid=0x3f94 runnable "GC task thread#3 (ParallelGC)" os_prio=0 tid=0x000000000346f000 nid=0x39b4 runnable "VM Periodic Task Thread" os_prio=2 tid=0x000000001bc25000 nid=0x1950 waiting on condition JNI global references: 338 Found one Java-level deadlock: ============================= "Thread-1": waiting to lock monitor 0x000000000354c3b8 (object 0x0000000780ae7e30, a java.lang.String), which is held by "Thread-0" "Thread-0": waiting to lock monitor 0x000000000354d7a8 (object 0x0000000780ae7e60, a java.lang.String), which is held by "Thread-1" Java stack information for the threads listed above: =================================================== "Thread-1": at com.example.demo.thread.DeadLockDemo.lambda$deadLock$1(DeadLockDemo.java:27) - waiting to lock <0x0000000780ae7e30> (a java.lang.String) - locked <0x0000000780ae7e60> (a java.lang.String) at com.example.demo.thread.DeadLockDemo$$Lambda$2/2128227771.run(Unknown Source) at java.lang.Thread.run(Thread.java:748) "Thread-0": at com.example.demo.thread.DeadLockDemo.lambda$deadLock$0(DeadLockDemo.java:20) - waiting to lock <0x0000000780ae7e60> (a java.lang.String) - locked <0x0000000780ae7e30> (a java.lang.String) at com.example.demo.thread.DeadLockDemo$$Lambda$1/2121055098.run(Unknown Source) at java.lang.Thread.run(Thread.java:748) Found 1 deadlock. 通过上面的线程Dump文件信息,我们可以看出来发生了死锁,下面也列出了java级别的锁问题和栈信息: ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTI5MzQzMjU_size_16_color_FFFFFF_t_70 1] 并且栈信息中,可以定位到死锁发生的地方。 如果解决死锁,那是因为代码的逻辑存在问题,可以调整代码的逻辑或者业务,来避免死锁。 ## 如何来避免死锁 ## * 避免一个线程同时获取多个锁 * 避免一个线程在锁内同时占用多个资源,尽量保证每个锁只占用一个资源 * 尝试使用定时锁,使用`lock.tryLock(timeout)`来替代使用内部锁机制。 * 对于数据库锁,加锁和解锁必须在一个数据库连接里,否则会出现解锁失败的情况。 ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTI5MzQzMjU_size_16_color_FFFFFF_t_70 2] [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTI5MzQzMjU_size_16_color_FFFFFF_t_70]: /images/20211220/988bfb5decbf4c3ea19fea59db88953c.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTI5MzQzMjU_size_16_color_FFFFFF_t_70 1]: /images/20211220/77413134613745fd892ebead0941ec6a.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTI5MzQzMjU_size_16_color_FFFFFF_t_70 2]: /images/20211220/b5a9a75290894b0c8cd71d94a63e1f7c.png
相关 多线程并发:Java线程同步死锁案例 在Java编程中,多线程并发和线程同步是两个重要的概念。下面我们将通过一个死锁的例子来深入理解。 首先,了解什么是死锁: - 死锁:两个或更多的线程因争夺资源而造成的一种互相 落日映苍穹つ/ 2024年09月18日 01:03/ 0 赞/ 14 阅读
相关 Java多线程编程:同步锁和死锁案例 Java多线程编程中,同步锁主要有两种方式:synchronized关键字和Lock接口。 1. `synchronized`关键字: ```java // 假设有一个共享 迷南。/ 2024年09月17日 14:57/ 0 赞/ 13 阅读
相关 Java多线程:死锁案例解析 死锁是多线程编程中的一种严重问题,当两个或更多的线程在执行过程中因争夺资源而造成的一种互相等待的现象称为死锁。 下面是一个简单的死锁案例,使用Java实现: ```java 爱被打了一巴掌/ 2024年09月10日 16:30/ 0 赞/ 23 阅读
相关 Java多线程问题:死锁案例 死锁是多线程编程中的一种严重问题,当两个或更多的线程因争夺资源而造成的一种互相等待的现象时,就会发生死锁。 下面是一个经典的死锁案例: ```java // 线程1,持有资 柔光的暖阳◎/ 2024年09月05日 19:18/ 0 赞/ 19 阅读
相关 JAVA多线程—线程死锁 程死锁: 创建两个字符串a和b,再创建两个线程A和B,让每个线程都用synchronized锁住字符串(A先锁a,再去锁b;B先锁b,再锁a),如果A锁住a,B锁住b,... 妖狐艹你老母/ 2024年04月17日 22:29/ 0 赞/ 49 阅读
相关 Java多线程 死锁转账案例 文章目录 两个转账的死锁demo 两个转账的死锁demo 需要两把锁: 转账时, 锁住自己的账户, 同时只能有一个线程去执行转账. 获取两把 - 日理万妓/ 2022年12月05日 01:37/ 0 赞/ 204 阅读
相关 java多线程死锁死锁案例 / 两个线程先分别持有两把锁,然后再去请求对方的锁,导致死锁 / public class DeadLock extends Thread 蔚落/ 2022年03月14日 11:18/ 0 赞/ 361 阅读
相关 Java多线程死锁案例 产生死锁的原因 就是,两个线程互相等待着对象释放锁,一直这样僵持下去,所以导致了死锁的产生,下面这个代码就会产生一个死锁: package com.exampl 落日映苍穹つ/ 2021年12月20日 04:09/ 0 赞/ 310 阅读
还没有评论,来说两句吧...