原创转载请注明出处:https://agilestyle.iteye.com/blog/2440433
死锁:一组互相竞争资源的线程因互相等待,导致“永久”阻塞的现象。
解决死锁,要么重启,要么规避
那如何避免死锁呢?要避免死锁就需要分析死锁发生的条件,只有以下这四个条件都发生时才会出现死锁:
1.互斥,共享资源 X 和 Y 只能被一个线程占用;
2.占有且等待,线程 T1 已经取得共享资源 X,在等待共享资源 Y 的时候,不释放共享资源 X;
3.不可抢占,其他线程不能强行抢占线程 T1 占有的资源;
4.循环等待,线程 T1 等待线程 T2 占有的资源,线程 T2 等待线程 T1 占有的资源,就是循环等待。
反过来分析,也就是说只要破坏其中一个,就可以成功避免死锁的发生。
模拟一个死锁的程序
DeadLockTest.java
package org.fool.test; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class DeadLockTest { private static Lock lockA = new ReentrantLock(); private static Lock lockB = new ReentrantLock(); public static void main(String args[]) { new Thread(new Runnable() { @Override public void run() { try { lockA.lock(); System.out.println("=====Thread A outer invoked...====="); TimeUnit.SECONDS.sleep(3); try { lockB.lock(); System.out.println("=====Thread A inner invoked...====="); } finally { lockB.unlock(); } } catch (InterruptedException e) { e.printStackTrace(); } finally { lockA.unlock(); } } }, "Thread-A").start(); new Thread(new Runnable() { @Override public void run() { try { lockB.lock(); System.out.println("=====Thread B outer invoked...====="); TimeUnit.SECONDS.sleep(3); try { lockA.lock(); System.out.println("=====Thread B inner invoked...====="); } finally { lockA.unlock(); } } catch (InterruptedException e) { e.printStackTrace(); } finally { lockB.unlock(); } } }, "Thread-B").start(); } }
打包成可执行jar包后,运行java -jar hello-deadlock-1.0-SNAPSHOT.jar
ps -ef | grep java 找出对应的pid,使用jstack打出堆栈信息
2019-04-25 15:49:30 Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.121-b13 mixed mode): "Attach Listener" #13 daemon prio=9 os_prio=31 tid=0x00007fb881058800 nid=0x1407 waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE "DestroyJavaVM" #12 prio=5 os_prio=31 tid=0x00007fb882802000 nid=0x1c03 waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE "Thread-B" #11 prio=5 os_prio=31 tid=0x00007fb883807000 nid=0x5903 waiting on condition [0x0000700002f89000] java.lang.Thread.State: WAITING (parking) at sun.misc.Unsafe.park(Native Method) - parking to wait for <0x000000076abdaa00> (a java.util.concurrent.locks.ReentrantLock$NonfairSync) at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175) at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:836) at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:870) at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1199) at java.util.concurrent.locks.ReentrantLock$NonfairSync.lock(ReentrantLock.java:209) at java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:285) at org.fool.test.DeadLockTest$2.run(DeadLockTest.java:41) at java.lang.Thread.run(Thread.java:745) "Thread-A" #10 prio=5 os_prio=31 tid=0x00007fb8800a7800 nid=0x5703 waiting on condition [0x0000700002e86000] java.lang.Thread.State: WAITING (parking) at sun.misc.Unsafe.park(Native Method) - parking to wait for <0x000000076abdaa30> (a java.util.concurrent.locks.ReentrantLock$NonfairSync) at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175) at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:836) at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:870) at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1199) at java.util.concurrent.locks.ReentrantLock$NonfairSync.lock(ReentrantLock.java:209) at java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:285) at org.fool.test.DeadLockTest$1.run(DeadLockTest.java:20) at java.lang.Thread.run(Thread.java:745) "Service Thread" #9 daemon prio=9 os_prio=31 tid=0x00007fb882051000 nid=0x5303 runnable [0x0000000000000000] java.lang.Thread.State: RUNNABLE "C1 CompilerThread3" #8 daemon prio=9 os_prio=31 tid=0x00007fb880009800 nid=0x5103 waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE "C2 CompilerThread2" #7 daemon prio=9 os_prio=31 tid=0x00007fb881044000 nid=0x4f03 waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE "C2 CompilerThread1" #6 daemon prio=9 os_prio=31 tid=0x00007fb881043000 nid=0x4d03 waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE "C2 CompilerThread0" #5 daemon prio=9 os_prio=31 tid=0x00007fb882025800 nid=0x4b03 waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE "Signal Dispatcher" #4 daemon prio=9 os_prio=31 tid=0x00007fb88200c800 nid=0x4903 runnable [0x0000000000000000] java.lang.Thread.State: RUNNABLE "Finalizer" #3 daemon prio=8 os_prio=31 tid=0x00007fb880858000 nid=0x3903 in Object.wait() [0x000070000266e000] java.lang.Thread.State: WAITING (on object monitor) at java.lang.Object.wait(Native Method) - waiting on <0x000000076ab08ec8> (a java.lang.ref.ReferenceQueue$Lock) at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143) - locked <0x000000076ab08ec8> (a java.lang.ref.ReferenceQueue$Lock) at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:164) at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:209) "Reference Handler" #2 daemon prio=10 os_prio=31 tid=0x00007fb880855800 nid=0x3703 in Object.wait() [0x000070000256b000] java.lang.Thread.State: WAITING (on object monitor) at java.lang.Object.wait(Native Method) - waiting on <0x000000076ab06b68> (a java.lang.ref.Reference$Lock) at java.lang.Object.wait(Object.java:502) at java.lang.ref.Reference.tryHandlePending(Reference.java:191) - locked <0x000000076ab06b68> (a java.lang.ref.Reference$Lock) at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153) "VM Thread" os_prio=31 tid=0x00007fb881002800 nid=0x3503 runnable "GC task thread#0 (ParallelGC)" os_prio=31 tid=0x00007fb880014800 nid=0x2503 runnable "GC task thread#1 (ParallelGC)" os_prio=31 tid=0x00007fb880015800 nid=0x2703 runnable "GC task thread#2 (ParallelGC)" os_prio=31 tid=0x00007fb880016000 nid=0x2903 runnable "GC task thread#3 (ParallelGC)" os_prio=31 tid=0x00007fb880016800 nid=0x2b03 runnable "GC task thread#4 (ParallelGC)" os_prio=31 tid=0x00007fb881001000 nid=0x2d03 runnable "GC task thread#5 (ParallelGC)" os_prio=31 tid=0x00007fb881002000 nid=0x2f03 runnable "GC task thread#6 (ParallelGC)" os_prio=31 tid=0x00007fb880800800 nid=0x3103 runnable "GC task thread#7 (ParallelGC)" os_prio=31 tid=0x00007fb880801000 nid=0x3303 runnable "VM Periodic Task Thread" os_prio=31 tid=0x00007fb880828800 nid=0x5503 waiting on condition JNI global references: 6 Found one Java-level deadlock: ============================= "Thread-B": waiting for ownable synchronizer 0x000000076abdaa00, (a java.util.concurrent.locks.ReentrantLock$NonfairSync), which is held by "Thread-A" "Thread-A": waiting for ownable synchronizer 0x000000076abdaa30, (a java.util.concurrent.locks.ReentrantLock$NonfairSync), which is held by "Thread-B" Java stack information for the threads listed above: =================================================== "Thread-B": at sun.misc.Unsafe.park(Native Method) - parking to wait for <0x000000076abdaa00> (a java.util.concurrent.locks.ReentrantLock$NonfairSync) at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175) at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:836) at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:870) at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1199) at java.util.concurrent.locks.ReentrantLock$NonfairSync.lock(ReentrantLock.java:209) at java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:285) at org.fool.test.DeadLockTest$2.run(DeadLockTest.java:41) at java.lang.Thread.run(Thread.java:745) "Thread-A": at sun.misc.Unsafe.park(Native Method) - parking to wait for <0x000000076abdaa30> (a java.util.concurrent.locks.ReentrantLock$NonfairSync) at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175) at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:836) at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:870) at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1199) at java.util.concurrent.locks.ReentrantLock$NonfairSync.lock(ReentrantLock.java:209) at java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:285) at org.fool.test.DeadLockTest$1.run(DeadLockTest.java:20) at java.lang.Thread.run(Thread.java:745) Found 1 deadlock.
Note:
tid: java线程ID
nid: native线程ID
相关推荐
线程死锁是多线程编程中一个严重的问题,它发生在两个或多个线程相互等待对方释放资源,导致它们都无法继续执行。这个概念在计算机科学中尤为重要,因为并发执行是提高系统性能的关键手段,但如果不妥善处理,死锁...
实测有效的一个c++检测线程死锁的解决方法(实现和测试代码) 原创实测有效的一个c++检测线程死锁的解决方法,已应用于项目,实测有效 原创文章地址:https://blog.csdn.net/liaozhilong88/article/details/80354414...
根据提供的文件内容,本篇报告主要涉及在Linux环境下通过C语言编程实现线程死锁的实验。报告中包含了一段实验代码,以及实验的基本框架和实验过程。下面详细解释报告中的知识点: 1. Linux系统与C语言编程: Linux...
DllMain 和多线程死锁 DllMain 是可选择的 DLL 入口指针,当进程和线程启动和终止时被系统调用,分别进行创建资源和释放资源等操作。在 DllMain 中创建线程或结束线程时,都特别要注意一个规则,那就是 DllMain 的...
Java 模拟线程死锁 线程死锁 在 Java 中,线程死锁(Deadlock)是一种特殊的情况,发生在两个或多个线程之间的互相等待对方释放资源的状态。这种情况下,各个线程都在等待其他线程释放资源,而自己也占用着其他...
### Java多线程死锁预防机制研究 #### 摘要 随着计算机技术的发展和软件系统日益复杂的背景下,多线程编程技术得到了广泛的应用。多线程能够显著提高程序的执行效率,但也随之带来了诸如死锁等问题。死锁是指两个或...
明白死锁产生的原因,在程序中演示死锁产生并从而实现多线程陈旭解决死锁(deadlock)这一类问题。
线程死锁是多线程编程中常见的问题,它发生在两个或多个线程相互等待对方释放资源而无法继续执行的情况。Lookcop是一款专门用于检测线程死锁的工具,对于保证程序的稳定性和效率至关重要。在Java等支持多线程的语言...
多线程死锁的危险 - 临界区函数的不当使用 在多线程编程中,临界区函数的使用是非常重要的。然而,许多开发者却忽视了临界区函数的正确使用方法,导致了多线程死锁的出现。本文将讲述一个关于在类的构造函数和析构...
线程死锁是多线程编程中一个严重的问题,它发生在两个或多个线程相互等待对方释放资源,导致它们都无法继续执行。CPU过高通常与过度的计算、无尽循环、死锁、线程竞争状态等问题相关。在Java编程中,WeakHashMap是一...
DllMain和多线程死锁问题 DllMain是Windows操作系统中的动态链接库(DLL)入口点,当进程和线程启动和终止时被系统调用,分别进行创建资源和释放资源等操作。在DllMain中创建线程或终止线程时,如果违背了DllMain的...
在处理多线程死锁时,一个重要的原则是避免循环等待。这意味着确保所有线程按相同顺序获取资源,以防止形成环路。此外,可以使用条件变量、信号量等高级同步机制来协调线程间的操作,或者使用死锁预防和死锁避免算法...
Java线程死锁是多线程编程中一个常见的问题,它发生在两个或多个线程相互等待对方释放资源,导致它们都无法继续执行的情况。死锁的发生通常涉及到四个必要条件:互斥、请求与保持、不剥夺和循环等待。理解并解决Java...
本资源为多线程中,多线程共享资源,出现死锁的情况。浅显易懂
一个简单有效的即时检测线程死锁的方法(附c++源代码) 原文链接:https://blog.csdn.net/liaozhilong88/article/details/80354414 原链接是windows下实现,这份代码以pthread简单实现跨平台 感谢原博主分享
定位进程中线程死锁检测工具
【标题】:“矩阵在计算机线程死锁的检测与防止中的应用1” 【主题】:本文探讨了在多线程操作系统中如何利用矩阵方法来检测和预防死锁问题。死锁是多进程环境下常见的问题,当多个进程互相等待对方持有的资源而...
进程、线程、死锁和POSIX规范的系统调用 进程是操作系统中一个独立的执行单元,它拥有自己的虚拟地址空间和系统资源。线程是轻量级的进程,它共享同一个进程的虚拟地址空间和系统资源。理解进程和线程的概念对于...
### 多线程死锁、活锁与竞争锁问题总结 #### 一、多线程基础知识简介 在探讨多线程编程中常见的问题之前,我们首先简要回顾一下多线程的基本概念。多线程是一种允许多个线程在同一进程中并发执行的技术。每个线程...