摘要:如何分析造成多線程的原因呢很多時(shí)候我們?cè)趹岩稍斐伤梨i的語(yǔ)句設(shè)置斷點(diǎn),單步調(diào)試,反而又不能重現(xiàn)了。有了,程序員不用對(duì)著冗長(zhǎng)燒腦的多線程代碼去冥思苦想了,會(huì)自動(dòng)把死鎖原因打印出來(lái),太方便了。
Java多線程編程也是Java面試中經(jīng)常考察的內(nèi)容。剛接觸Java多線程編程的朋友們,可能會(huì)不慎寫(xiě)出一些會(huì)導(dǎo)致死鎖(deadlock)的應(yīng)用出來(lái)。如何分析造成Java多線程的原因呢?很多時(shí)候我們?cè)趹岩稍斐伤梨i的語(yǔ)句設(shè)置斷點(diǎn),單步調(diào)試,反而又不能重現(xiàn)了。這種現(xiàn)象很正常,因?yàn)樵蹅儐尾秸{(diào)試和直接運(yùn)行程序,代碼執(zhí)行的時(shí)序是不同的,很可能無(wú)法滿足死鎖的觸發(fā)條件。
實(shí)際上,JDK已經(jīng)給Java程序員提供了強(qiáng)大的死鎖分析工具,能夠直接分析一個(gè)正在運(yùn)行的并且處于死鎖狀態(tài)的應(yīng)用,并給出具體是哪一行Java代碼引起的死鎖。
這篇文章就以一個(gè)例子來(lái)給大家演示如何使用這個(gè)JDK提供的標(biāo)準(zhǔn)工具。
這個(gè)工具叫jstack,就是JDK安裝目錄的bin文件夾下的一個(gè)執(zhí)行文件。
我們首先寫(xiě)一個(gè)會(huì)導(dǎo)致死鎖的應(yīng)用出來(lái)。
public class DeadLockExample { public static void main(String[] args) { final String resource1 = "ABAP"; final String resource2 = "Java"; Thread t1 = new Thread() { public void run() { synchronized (resource1) { System.out.println("Thread 1: locked resource 1"); try { Thread.sleep(100); } catch (Exception e) { } synchronized (resource2) { System.out.println("Thread 1: locked resource 2"); } } } } ; Thread t2 = new Thread() { public void run() { synchronized (resource2) { System.out.println("Thread 2: locked resource 2"); try { Thread.sleep(100); } catch (Exception e) { } synchronized (resource1) { System.out.println("Thread 2: locked resource 1"); } } } } ; t1.start(); t2.start(); } }
這個(gè)應(yīng)用思路很簡(jiǎn)單,同時(shí)啟動(dòng)兩個(gè)線程,分別鎖住了resource1和resource2,然后休眠0.1秒,接著分別嘗試去請(qǐng)求資源resource2和resource1。
執(zhí)行應(yīng)用,在控制臺(tái)打印出下列輸出后,進(jìn)入死鎖狀態(tài):
Thread 1: locked resource 1
Thread 2: locked resource 2
使用命令行 jps -l -m找到處于死鎖狀態(tài)應(yīng)用的進(jìn)程id。從下圖得知死鎖進(jìn)程為51476:
然后使用命令行jstack 51476打印這個(gè)進(jìn)程的運(yùn)行棧信息。
我上圖紅色高亮出的 0x00000000d6f64988 和 0x00000000d6f649b8代表了代碼中的兩個(gè)資源“ABAP” 和“Java”。
jstack打印的輸出非常清晰,顯示了具體哪行Java代碼試圖去鎖定哪一個(gè)Java資源(下圖的waiting to lock)但是沒(méi)有成功, 并且將失敗的原因,即擁有當(dāng)前請(qǐng)求資源的線程名稱(chēng)也打印了出來(lái)。
有了jstack,Java程序員不用對(duì)著冗長(zhǎng)燒腦的多線程代碼去冥思苦想了,JDK會(huì)自動(dòng)把死鎖原因打印出來(lái),太方便了。
要獲取更多Jerry的原創(chuàng)技術(shù)文章,請(qǐng)關(guān)注公眾號(hào)"汪子熙"或者掃描下面二維碼:
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/71821.html
摘要:采用的生成非波拉契數(shù)列提供了原生的支持,語(yǔ)法非常有特色,關(guān)鍵字后面緊跟一個(gè)星號(hào)。的詳細(xì)介紹參考官網(wǎng)先看如何用這個(gè)黑科技重新實(shí)現(xiàn)非波拉契樹(shù)立的生成。在這個(gè)內(nèi)部,我們定義了一個(gè)無(wú)限循環(huán),用于計(jì)算非波拉契數(shù)列。 程序員面試系列 Java面試系列-webapp文件夾和WebContent文件夾的區(qū)別? 程序員面試系列:Spring MVC能響應(yīng)HTTP請(qǐng)求的原因? Java程序員面試系列-什么...
摘要:此時(shí)線程需要鎖才能繼續(xù)往下執(zhí)行。但是線程的鎖并沒(méi)有釋放,線程的鎖也沒(méi)有釋放。 前言 只有光頭才能變強(qiáng) 回顧前面: ThreadLocal就是這么簡(jiǎn)單 多線程三分鐘就可以入個(gè)門(mén)了! 多線程基礎(chǔ)必要知識(shí)點(diǎn)!看了學(xué)習(xí)多線程事半功倍 Java鎖機(jī)制了解一下 AQS簡(jiǎn)簡(jiǎn)單單過(guò)一遍 Lock鎖子類(lèi)了解一下 線程池你真不來(lái)了解一下嗎? 本篇主要是講解死鎖,這是我在多線程的最后一篇了。主要將多線程...
摘要:橋接模式的核心在于將抽象部分和它的實(shí)現(xiàn)部分分離,使它們都可以獨(dú)立的變化。看起來(lái)這個(gè)版本已經(jīng)很完美了不,它仍然有可以?xún)?yōu)化的空間,即題目提到的橋接模式。使用橋接模式的實(shí)現(xiàn)版本這個(gè)實(shí)現(xiàn)包含了三個(gè)函數(shù)。這個(gè)例子體現(xiàn)了橋接模式的作用。 我寫(xiě)的程序員面試系列文章 Java面試系列-webapp文件夾和WebContent文件夾的區(qū)別? 程序員面試系列:Spring MVC能響應(yīng)HTTP請(qǐng)求的原因?...
摘要:點(diǎn)擊進(jìn)入我的博客命令行工具這些工具大多數(shù)是類(lèi)庫(kù)的一層薄的包裝,它們的主要功能代碼是在類(lèi)庫(kù)中實(shí)現(xiàn)的??梢暬ぞ呤堑侥壳盀橹闺S發(fā)布的功能最強(qiáng)大的運(yùn)行監(jiān)視和故障處理程序,并且可以預(yù)見(jiàn)在未來(lái)一段時(shí)間內(nèi)都是官方主力發(fā)展的虛擬機(jī)故障處理工具。 點(diǎn)擊進(jìn)入我的博客 3.1 JDK命令行工具 showImg(https://segmentfault.com/img/remote/14600000174...
摘要:線程的優(yōu)先級(jí)代表線程的優(yōu)先級(jí)為線程代表線程為,而代表該線程對(duì)應(yīng)的操作系統(tǒng)級(jí)別的線程。若是有運(yùn)行圖形界面的環(huán)境,也可以使用一些圖形化的工具,例如來(lái)生成線程棧文件。使用線程棧定位問(wèn)題發(fā)現(xiàn)死鎖當(dāng)兩個(gè)或多個(gè)線程正在等待被對(duì)方占有的鎖,死鎖就會(huì)發(fā)生。 什么是線程棧(thread dump) 線程棧是某個(gè)時(shí)間點(diǎn),JVM所有線程的活動(dòng)狀態(tài)的一個(gè)匯總;通過(guò)線程棧,可以查看某個(gè)時(shí)間點(diǎn),各個(gè)線程正在做什么...
閱讀 1118·2021-11-23 09:51
閱讀 1081·2021-10-18 13:31
閱讀 2991·2021-09-22 16:06
閱讀 4284·2021-09-10 11:19
閱讀 2206·2019-08-29 17:04
閱讀 437·2019-08-29 10:55
閱讀 2485·2019-08-26 16:37
閱讀 3381·2019-08-26 13:29