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

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

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

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

構(gòu)造死鎖

編寫代碼,啟動2個線程,Thread1拿到了obj1鎖,準(zhǔn)備去拿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運(yùn)行

#運(yùn)行結(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進(jìn)行分析

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)生的四個必要條件

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

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

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

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

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

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

進(jìn)程推進(jìn)順序非法:進(jìn)程在運(yùn)行過程中,請求和釋放資源的順序不當(dāng),也同樣會導(dǎo)致死鎖。

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

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

如何避免死鎖呢

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

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

所以對于剩下三個我們可以逐一進(jìn)行分析

1.加鎖時限

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

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

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

3.加鎖順序

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

可以靠按序申請資源來進(jìn)行預(yù)防。

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

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

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

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

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

相關(guān)文章

最新評論

漠河县| 陵川县| 武隆县| 万年县| 达日县| 张家港市| 陆丰市| 张掖市| 墨玉县| 青州市| 广汉市| 郧西县| 吉林省| 博客| 九台市| 栾城县| 边坝县| 麻城市| 如皋市| 同仁县| 玛纳斯县| 达州市| 凤台县| 西青区| 株洲市| 隆尧县| 耿马| 锡林浩特市| 股票| 古浪县| 新干县| 绥德县| 调兵山市| 马关县| 神池县| 新安县| 墨脱县| 安国市| 淮安市| 禹州市| 赤壁市|