1. 程式人生 > >一文學會Java死鎖和CPU 100% 問題的排查技巧

一文學會Java死鎖和CPU 100% 問題的排查技巧

做一個積極的人

編碼、改bug、提升自己

我有一個樂園,面向程式設計,春暖花開

工欲善其事,必先利其器

 

 

00 本文簡介

作為一名搞技術的程式猿或者是攻城獅,想必你應該是對下面這兩個問題有所瞭解,說不定你在實際的工作或者面試就有遇到過:

第一個問題:Java死鎖如何排查和解決?

第二個問題:伺服器CPU佔用率高達到100%排查和解決?

第三個問題:有哪些工具能夠快速檢視執行緒使用情況?

本文對這三個問題進行總結整理,通過例項演示講解,精彩乾貨,不容錯過啊!

前戲就這麼多,高潮會很多,做好了,讓我們直奔主題,發動小船,Let's go!

01 Java死鎖排查和解決

要排查和解決死鎖,首先思考三個問題:

1. 什麼是死鎖?

2. 為什麼會出現死鎖?

3. 怎麼排查程式碼中出現了死鎖?

4. 如何避免寫出死鎖的程式碼?

作為技術人員(工程師),在出現問題的時候,能夠儘快的去解決這個問題。但是在學習技術知識的時候,還是腳踏實地,多問一些為什麼,一個好的問題,能夠讓自己思考,這方面的能力也一定要鍛鍊鍛鍊哦,這樣才能更好的理解和掌握知識,並探究/觸碰到更深入的地方。

1、啥是死鎖?

死鎖是指兩個或兩個以上的程序在執行過程中,由於競爭資源或者由於彼此通訊而造成的一種阻塞的現象,若無外力作用,它們都將無法推進下去。此時稱系統處於死鎖狀態或系統產生了死鎖,這些永遠在互相等待的程序稱為死鎖程序。[百度百科:死鎖]

注:程序和執行緒都可以發生死鎖,只要滿足死鎖的條件!

2、為啥子會出現死鎖?

從上面的概念中我們知道

(1)必須是兩個或者兩個以上程序(執行緒)

(2)必須有競爭資源

3、怎麼排查程式碼中出現了死鎖?【重點來了】

首先整一個死鎖的程式碼,看例子:

上面這段程式碼執行後,就會出現死鎖,那麼排查的方法有如下:

第一個姿勢:使用 jps + jstack

一:在windons命令視窗,使用jps -l【不會使用jps請自行查詢資料】

二:使用 jstack -l 12316 【不會使用jstack請自行查詢資料】

第二個姿勢:使用jconsole

在window開啟 JConsole,JConsole是一個圖形化的監控工具!

一:在windons命令視窗 ,輸出 JConsole,如下圖:

二:選擇到執行緒的tab上,如下截圖。

第三個姿勢:使用Java Visual VM

在window開啟 jvisualvm,jvisualvm是一個圖形化的監控工具!

一:在windons命令視窗 ,輸出 jvisualvm

二:依然是切換到執行緒這個TAB上,很明顯的就有提示!

4、如何避免死鎖?

上面說了死鎖出現的原因以及通過三種方式來檢測和排查死鎖,下面更重要的東西來了,就是如何避免死鎖,如果能夠讓寫出的程式碼避免死鎖出現也就沒有上面這些排查的過程了。最好的是從源頭控制問題,而不是後期遇到問題在去填坑。

我看了阿里巴巴中最新的開發規約,裡面有對避免死鎖的說明,具體如下:


【強制】對多個資源、資料庫表、物件同時加鎖時,需要保持一致的加鎖順序,否則可能會 造成死鎖。 說明:執行緒一需要對錶 A、B、C 依次全部加鎖後才可以進行更新操作,那麼執行緒二的加鎖順序也必須是 A、B、C,否則可能出現死鎖。


02、Java CPU 100% 排查技巧

第一個姿勢,步驟有點多,難度四星

平時多積累一點,這樣在遇到問題的時候就少句求人的話。如果在實際的開發中遇到CPU 100%問題,要怎麼排查呢?如果你沒有遇到過這個問題,請先自己思考10s,如果你遇到過,這個時候也正好可以在回顧一遍。

一、 使用top命令檢視cpu佔用資源較高的PID

當前佔用cup100% 的PID為3455。

二、通過jps找到當前使用者下的java程式PID

執行jps -l能夠打印出所有的應用的PID,找到有一個PID和這個cpu使用100%一樣的ID!!!就知道是哪一個服務了。知道了對應的服務,在接著後續的分析步驟。

三、 使用 pidstat -p < PID > 1 3 -u -t

-p:指定程序號
-u:預設的引數,顯示各個程序的cpu使用統計
-t:顯示選擇任務的執行緒的統計資訊外的額外資訊

四、找到cpu佔用較高的執行緒TID ,通過上圖發現是 3467的TID佔用cup較大

五、 因為jstack命令輸出檔案記錄的執行緒ID是16進位制。因此我們先將TID轉換為十六進位制的表示方式,轉換方式可以參考下圖。

3467轉為十六進位制 d8d,注意是小寫!! 記錄下來,後面會使用。

六、通過jstack [-l] PID輸出當前程序的執行緒資訊

jstack PID  /temp/test.log

七、查詢 TID對應的執行緒(輸出的執行緒id為十六進位制),找到對應的程式碼,使用命令查詢哦,不要肉眼比對,具體命令請思考,給你表現機會。

找到之後具體分析這個執行緒在幹什麼,為什麼會佔用這麼多的 CUP資源。

PS:執行緒的幾種狀態如下說明:

NEW,未啟動的。不會出現在Dump中。
RUNNABLE,在虛擬機器內執行的。
BLOCKED,受阻塞並等待監視器鎖。
WATING,無限期等待另一個執行緒執行特定操作。
TIMED_WATING,有時限的等待另一個執行緒的特定操作。
TERMINATED,已退出的。

第二個姿勢,待開發[奸笑臉]

此處省略……,好多字。

03 推薦兩個高效排查問題工具

一 :show-busy-java-threads

官網地址:show-busy-java-threads: https://github.com/oldratlee/useful-scripts/blob/master/docs/java.md#-show-busy-java-threads

簡單安裝和使用過程:

  1. 下載 show-busy-java-threads
  2. 上傳伺服器,然後進行解壓
  3. 然後執行對應的命令

二:阿里開源的問題定位神器 arthas 來定位問題。

官網地址:arthas :https://alibaba.github.io/arthas/index.html

這個裡面有很多命令,如thread 支援一鍵展示當前最忙的前N個執行緒並列印堆疊,最簡單的 thread -n 10 即可將最忙碌的十個執行緒快照打印出來,真正高效。

定位神器 arthas 安裝過程就做介紹了,如果你還沒有用過這個工具,我建議一定去用一下,說不定你會愛上它!

04 總結

本文內容比較多,基本上是手把手的教程了,希望能夠對你有所幫助,也建議沒有遇到類似問題的夥伴,看完之後一定要親自去實踐一下操作過程,如果沒有環境可以自行想辦法搞一個測試例子。還是老話:不要眼高手低,看了和做了本質上兩個概念,最終收穫的也一定不同。

05 彩蛋-另一個姿勢

也可以通過使用jstack找到系統的程式碼效能問題

1、在進行壓力測試的時候,使用jps找到應用的PID

2、然後使用jstack輸出出壓力測試時候應用的dump資訊

3、分析輸出的日誌檔案中那個方法block執行緒佔用最多,這裡可能是效能有問題,找到對應的程式碼分析


謝謝你的閱讀,如果您覺得這篇博文對你有幫助,請點贊或者喜歡,讓更多的人看到!祝你每天開心愉快!


 

不管做什麼,只要堅持下去就會看到不一樣!在路上,不卑不亢!

 

願你我在人生的路上能都變成最好的自己,能夠成為一個獨擋一面的人

© 每天都在變得更好的阿