最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JVM?jstack實戰(zhàn)之死鎖問題詳解

 更新時間:2022年10月11日 08:20:14   作者:共飲一杯無  
如果在生產(chǎn)環(huán)境發(fā)生了死鎖,我們將看到的是部署的程序沒有任何反應了,這個時候我們可以借助?jstack進行分析,下面我們實戰(zhàn)操作查找死鎖的原因

如果在生產(chǎn)環(huán)境發(fā)生了死鎖,我們將看到的是部署的程序沒有任何反應了,這個時候我們可以借助 jstack進行分析,下面我們實戰(zhàn)操作查找死鎖的原因。所謂死鎖指的是是一組互相競爭資源的線程因互相等待導致“永久”阻塞的現(xiàn)象。

構(gòu)造死鎖

編寫代碼,啟動2個線程,Thread1拿到了obj1鎖,準備去拿obj2鎖時,obj2已經(jīng)被Thread2鎖定,所以發(fā)送了死鎖。

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

}

在idea運行

#運行結(jié)果
E:\Java\jdk8u171\bin\java.exe "-javaagent:C:\idea\IntelliJ IDEA 2019.3.2\lib\idea_rt.jar=50268:C:\idea\IntelliJ IDEA 2019.3.2\bin" -Dfile.encoding=UTF-8 -classpath E:\Java\jdk8u171\jre\lib\charsets.jar;E:\Java\jdk8u171\jre\lib\deploy.jar;E:\Java\jdk8u171\jre\lib\ext\access-bridge-64.jar;E:\Java\jdk8u171\jre\lib\ext\cldrdata.jar;E:\Java\jdk8u171\jre\lib\ext\dnsns.jar;E:\Java\jdk8u171\jre\lib\ext\jaccess.jar;E:\Java\jdk8u171\jre\lib\ext\jfxrt.jar;E:\Java\jdk8u171\jre\lib\ext\localedata.jar;E:\Java\jdk8u171\jre\lib\ext\nashorn.jar;E:\Java\jdk8u171\jre\lib\ext\sunec.jar;E:\Java\jdk8u171\jre\lib\ext\sunjce_provider.jar;E:\Java\jdk8u171\jre\lib\ext\sunmscapi.jar;E:\Java\jdk8u171\jre\lib\ext\sunpkcs11.jar;E:\Java\jdk8u171\jre\lib\ext\zipfs.jar;E:\Java\jdk8u171\jre\lib\javaws.jar;E:\Java\jdk8u171\jre\lib\jce.jar;E:\Java\jdk8u171\jre\lib\jfr.jar;E:\Java\jdk8u171\jre\lib\jfxswt.jar;E:\Java\jdk8u171\jre\lib\jsse.jar;E:\Java\jdk8u171\jre\lib\management-agent.jar;E:\Java\jdk8u171\jre\lib\plugin.jar;E:\Java\jdk8u171\jre\lib\resources.jar;E:\Java\jdk8u171\jre\lib\rt.jar;E:\jvm-test\target\classes cn.zjq.jvm.TestDeadLock
Thread1 拿到了 obj1 的鎖!
Thread2 拿到了 obj2 的鎖!
#這里發(fā)生了死鎖,程序一直將等待下去

使用jstack進行分析

C:\Users\dell>jps
12624 Launcher
5140 org.eclipse.equinox.launcher_1.5.0.v20180512-1130.jar
7204
17000 Jps
18536 KotlinCompileDaemon
17196 TestDeadLock
29916 RemoteMavenServer

C:\Users\dell> jstack 17196
2021-07-25 21:52:25
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.171-b11 mixed mode):

"DestroyJavaVM" #14 prio=5 os_prio=0 tid=0x00000000029f2800 nid=0x1868 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Thread-1" #13 prio=5 os_prio=0 tid=0x000000001e5d3000 nid=0x6994 waiting for monitor entry [0x000000001f49f000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at cn.zjq.jvm.TestDeadLock$Thread2.run(TestDeadLock.java:49)
        - waiting to lock <0x000000076b688680> (a java.lang.Object)
        - locked <0x000000076b688690> (a java.lang.Object)
        at java.lang.Thread.run(Thread.java:748)

"Thread-0" #12 prio=5 os_prio=0 tid=0x000000001e5d2000 nid=0x21d8 waiting for monitor entry [0x000000001f39f000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at cn.zjq.jvm.TestDeadLock$Thread1.run(TestDeadLock.java:29)
        - waiting to lock <0x000000076b688690> (a java.lang.Object)
        - locked <0x000000076b688680> (a java.lang.Object)
        at java.lang.Thread.run(Thread.java:748)

"Service Thread" #11 daemon prio=9 os_prio=0 tid=0x000000001e5aa800 nid=0x6e40 runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

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

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

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

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

"Monitor Ctrl-Break" #6 daemon prio=5 os_prio=0 tid=0x000000001e4ff800 nid=0x5040 runnable [0x000000001ec9e000]
   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 <0x000000076b7d0200> (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 <0x000000076b7d0200> (a java.io.InputStreamReader)
        at java.io.BufferedReader.readLine(BufferedReader.java:389)
        at com.intellij.rt.execution.application.AppMainV2$1.run(AppMainV2.java:64)

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

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

"Finalizer" #3 daemon prio=8 os_prio=1 tid=0x000000001e441800 nid=0x2c0c in Object.wait() [0x000000001e91e000]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x000000076b508ed0> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143)
        - locked <0x000000076b508ed0> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:164)
        at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:212)

"Reference Handler" #2 daemon prio=10 os_prio=2 tid=0x000000001c54d000 nid=0x6508 in Object.wait() [0x000000001e41f000]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x000000076b506bf8> (a java.lang.ref.Reference$Lock)
        at java.lang.Object.wait(Object.java:502)
        at java.lang.ref.Reference.tryHandlePending(Reference.java:191)
        - locked <0x000000076b506bf8> (a java.lang.ref.Reference$Lock)
        at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)

"VM Thread" os_prio=2 tid=0x000000001c549000 nid=0x5af4 runnable

"GC task thread#0 (ParallelGC)" os_prio=0 tid=0x0000000002a08800 nid=0x347c runnable

"GC task thread#1 (ParallelGC)" os_prio=0 tid=0x0000000002a0a000 nid=0x6bc8 runnable

"GC task thread#2 (ParallelGC)" os_prio=0 tid=0x0000000002a0b800 nid=0x7d20 runnable

"GC task thread#3 (ParallelGC)" os_prio=0 tid=0x0000000002a0d000 nid=0x728c runnable

"GC task thread#4 (ParallelGC)" os_prio=0 tid=0x0000000002a0f800 nid=0x595c runnable

"GC task thread#5 (ParallelGC)" os_prio=0 tid=0x0000000002a10800 nid=0x43fc runnable

"GC task thread#6 (ParallelGC)" os_prio=0 tid=0x0000000002a14800 nid=0x3c50 runnable

"GC task thread#7 (ParallelGC)" os_prio=0 tid=0x0000000002a16000 nid=0x364c runnable

"VM Periodic Task Thread" os_prio=2 tid=0x000000001e5ca000 nid=0x1da4 waiting on condition

JNI global references: 12


Found one Java-level deadlock:
=============================
"Thread-1":
  waiting to lock monitor 0x000000001c5535f8 (object 0x000000076b688680, a java.lang.Object),
  which is held by "Thread-0"
"Thread-0":
  waiting to lock monitor 0x000000001c550d68 (object 0x000000076b688690, a java.lang.Object),
  which is held by "Thread-1"

Java stack information for the threads listed above:
===================================================
"Thread-1":
        at cn.zjq.jvm.TestDeadLock$Thread2.run(TestDeadLock.java:49)
        - waiting to lock <0x000000076b688680> (a java.lang.Object)
        - locked <0x000000076b688690> (a java.lang.Object)
        at java.lang.Thread.run(Thread.java:748)
"Thread-0":
        at cn.zjq.jvm.TestDeadLock$Thread1.run(TestDeadLock.java:29)
        - waiting to lock <0x000000076b688690> (a java.lang.Object)
        - locked <0x000000076b688680> (a java.lang.Object)
        at java.lang.Thread.run(Thread.java:748)

Found 1 deadlock.

在輸出的信息中,已經(jīng)看到,發(fā)現(xiàn)了1個死鎖,關(guān)鍵看這個:

可以清晰的看到:

Thread2獲取了<0x000000076b688690> 的鎖,等待獲取<0x000000076b688680>這個鎖

Thread1獲取了<0x000000076b688680> 的鎖,等待獲取<0x000000076b688690>這個鎖

由此可見,發(fā)生了死鎖。

怎么避免死鎖

死鎖產(chǎn)生的四個必要條件

互斥使用,即當資源被一個線程使用(占有)時,別的線程不能使用

不可搶占,資源請求者不能強制從資源占有者手中奪取資源,資源只能由資源占有者主動釋放。

請求和保持,即當資源請求者在請求其他的資源的同時保持對原有資源的占有。

循環(huán)等待,即存在一個等待隊列:T1等待占有T2的資源,T2等待占有T3的資源,T3等待占有T1的資源。這樣就形成了一個等待環(huán)路。

死鎖產(chǎn)生的原因

系統(tǒng)資源的競爭:通常系統(tǒng)中擁有的不可剝奪資源,其數(shù)量不足以滿足多個進程運行的需要,使得進程在運行過程中,會因爭奪資源而陷入僵局。只有對不可剝奪資源的競爭 才可能產(chǎn)生死鎖,對可剝奪資源的競爭是不會引起死鎖的。

進程推進順序非法:進程在運行過程中,請求和釋放資源的順序不當,也同樣會導致死鎖。

信號量使用不當也會造成死鎖:進程間彼此相互等待對方發(fā)來的消息,結(jié)果也會使得這些進程間無法繼續(xù)向前推進。

死鎖產(chǎn)生的四個必要條件

如何避免死鎖呢

既然發(fā)生死鎖的原因是需要同時滿足四個必要條件,我們只需要打破其中任意一個條件即可避免死鎖問題。

而在這四個條件中第一個互斥條件是無法被破壞的,因為鎖本身就是通過互斥來解決線程安全問題的。

所以對于剩下三個我們可以逐一進行分析

1.加鎖時限

對于不可搶占這個條件占用部分資源的線程進一步申請其他資源時,如果申請不到可以主動釋放它占有的資源,這樣不可搶占這個條件就破壞掉了。線程嘗試獲取鎖的時候加上一定的時限,超過時限則放棄對該鎖的請求,并釋放自己占有的鎖。

2.一次性獲取所有鎖資源

我們可以一次性申請所有的鎖資源,這樣就不存在請求和保持條件了

3.加鎖順序

當多個線程需要相同的一些鎖,但是按照不同的順序加鎖,死鎖就很容易發(fā)生。對于循環(huán)等待這個條件

可以靠按序申請資源來進行預防。

如果能確保所有的線程都是按照相同的順序獲得鎖,那么死鎖就不會發(fā)生。

如果一個線程(比如線程3)需要一些鎖,那么它必須按照確定的順序獲取鎖。它只有獲得了從順序上排在前面的鎖之后,才能獲取后面的鎖。

例如,線程2和線程3只有在獲取了鎖A之后才能嘗試獲取鎖C(譯者注:獲取鎖A是獲取鎖C的必要條件)。因為線程1已經(jīng)擁有了鎖A,所以線程2和3需要一直等到鎖A被釋放。然后在它們嘗試對B或C加鎖之前,必須成功地對A加了鎖。

按照順序加鎖是一種有效的死鎖預防機制。但是,這種方式需要你事先知道所有可能會用到的鎖(譯者注:并對這些鎖做適當?shù)呐判?,但總有些時候是無法預知的。

到此這篇關(guān)于JVM jstack實戰(zhàn)之死鎖問題詳解的文章就介紹到這了,更多相關(guān)JVM jstack死鎖內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 詳解Spring Boot配置排序依賴技巧

    詳解Spring Boot配置排序依賴技巧

    本篇文章主要介紹了Spring Boot配置排序依賴技巧,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-11-11
  • SpringBoot使用自動配置xxxAutoConfiguration

    SpringBoot使用自動配置xxxAutoConfiguration

    這篇文章介紹了SpringBoot自動配置xxxAutoConfiguration的使用方法,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-12-12
  • springcloud連接遠程nacos失敗顯示localhost服務連接失敗的問題解決

    springcloud連接遠程nacos失敗顯示localhost服務連接失敗的問題解決

    這篇文章主要介紹了springcloud連接遠程nacos失敗顯示localhost服務連接失敗的問題解決,文中有詳細的代碼示例供大家參考,對大家解決問題有一定的幫助,需要的朋友可以參考下
    2024-03-03
  • Java實現(xiàn)Word/Pdf/TXT轉(zhuǎn)html的實例代碼

    Java實現(xiàn)Word/Pdf/TXT轉(zhuǎn)html的實例代碼

    本文主要介紹了Java實現(xiàn)Word/Pdf/TXT轉(zhuǎn)html的實例代碼,代碼簡單易懂,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-02-02
  • Java 8中HashMap的底層原理解析

    Java 8中HashMap的底層原理解析

    HashMap作為Java中常用的數(shù)據(jù)結(jié)構(gòu)之一,在JDK 1.8中經(jīng)過了一系列的優(yōu)化和改進,深入理解其底層原理,包括哈希算法、數(shù)組與鏈表結(jié)構(gòu)、紅黑樹的引入等,有助于更好地使用和理解HashMap的性能特性,這篇文章主要介紹了Java 8中HashMap的底層原理,需要的朋友可以參考下
    2023-11-11
  • OpenCV實現(xiàn)普通閾值

    OpenCV實現(xiàn)普通閾值

    這篇文章主要為大家詳細介紹了OpenCV實現(xiàn)普通閾值,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-11-11
  • spring的同一定時任務上一次的任務未結(jié)束前不會啟動這次任務問題

    spring的同一定時任務上一次的任務未結(jié)束前不會啟動這次任務問題

    這篇文章主要介紹了spring的同一定時任務上一次的任務未結(jié)束前不會啟動這次任務問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-12-12
  • SpringBoot項目啟動報錯踩坑實戰(zhàn)記錄

    SpringBoot項目啟動報錯踩坑實戰(zhàn)記錄

    這篇文章主要給大家介紹了關(guān)于SpringBoot項目啟動報錯踩坑的相關(guān)資料,文中通過實例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2023-02-02
  • HashMap和List遍歷方法及如何遍歷刪除元素總結(jié)

    HashMap和List遍歷方法及如何遍歷刪除元素總結(jié)

    在本篇文章中小編給大家分享了關(guān)于HashMap和List遍歷方法及如何遍歷刪除元素知識點總結(jié),需要的朋友們參考下。
    2019-05-05
  • mybatis返回map類型數(shù)據(jù)空值字段不顯示的解決方案

    mybatis返回map類型數(shù)據(jù)空值字段不顯示的解決方案

    這篇文章主要介紹了mybatis返回map類型數(shù)據(jù)空值字段不顯示的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-03-03

最新評論

东乡族自治县| 云安县| 乾安县| 龙川县| 钟山县| 宝兴县| 天等县| 荆州市| 余干县| 桐乡市| 阿瓦提县| 玛纳斯县| 平武县| 桐城市| 龙江县| 班玛县| 夹江县| 泰兴市| 陇南市| 烟台市| 安吉县| 清涧县| 南安市| 新宾| 绿春县| 株洲县| 汽车| 孝感市| 和平区| 商丘市| 阜新| 丽水市| 喀什市| 太仓市| 新乡县| 孟村| 阳春市| 工布江达县| 铅山县| 蕉岭县| 保山市|