java线程死锁_Java线程死锁–案例研究
java線程死鎖
本文將描述從在IBM JVM 1.6上運(yùn)行的Weblogic 11g生產(chǎn)系統(tǒng)中觀察到的最新Java死鎖問題的完整根本原因分析。此案例研究還將證明掌握線程轉(zhuǎn)儲分析技能的重要性; 包括用于IBM JVM Thread Dump格式。
環(huán)境規(guī)格
– Java EE服務(wù)器:Oracle Weblogic Server 11g和Spring 2.0.5 –操作系統(tǒng):AIX 5.3 – Java VM:IBM JRE 1.6.0 –平臺類型:門戶和訂購應(yīng)用程序
監(jiān)控和故障排除工具
– JVM線程轉(zhuǎn)儲(IBM JVM格式)– Compuware Server Vantage(Weblogic JMX監(jiān)視和警報(bào))
問題概述
從Compuware Server Vantage觀察到并報(bào)告了一個(gè)嚴(yán)重的線程阻塞問題,該問題影響了我們的2臺Weblogic 11g生產(chǎn)托管服務(wù)器,從而導(dǎo)致了最終用戶的應(yīng)用程序影響和超時(shí)情況。
事實(shí)的收集和驗(yàn)證
像往常一樣,Java EE問題調(diào)查需要收集技術(shù)和非技術(shù)事實(shí),因此我們可以得出其他事實(shí)和/或就根本原因進(jìn)行結(jié)論。 在采取糾正措施之前,要對以下事實(shí)進(jìn)行驗(yàn)證,以便得出根本原因:
·對客戶有什么影響? 中(在16個(gè)中只有2個(gè)受管服務(wù)器/ JVM受影響)·受影響平臺的最新更改? 是(新的與JMS相關(guān)的異步組件)·最近到受影響平臺的流量增加了嗎? 否·這個(gè)問題如何表現(xiàn)出來? 觀察到線程突然增加,導(dǎo)致線程快速耗盡。·Weblogic托管服務(wù)器重新啟動是否解決了問題? 是的,但是幾個(gè)小時(shí)后問題又回來了(不可預(yù)測的間歇性模式)
– 結(jié)論1 :
該問題與間歇性卡住的線程行為有關(guān),該行為當(dāng)時(shí)僅影響少數(shù)Weblogic托管服務(wù)器
– 結(jié)論2 :
由于問題是斷斷續(xù)續(xù)的,因此不太可能出現(xiàn)全局根本原因,例如下游系統(tǒng)無響應(yīng)
線程轉(zhuǎn)儲分析–第一遍
處理滯留的線程問題時(shí),要做的第一件事是生成JVM線程轉(zhuǎn)儲。 無論您的環(huán)境規(guī)格和問題背景如何,這都是一條黃金法則。 JVM線程轉(zhuǎn)儲快照為您提供了有關(guān)活動線程及其當(dāng)時(shí)正在執(zhí)行的處理/任務(wù)類型的重要信息。
現(xiàn)在回到我們的案例研究,生成了一個(gè)IBM JVM線程轉(zhuǎn)儲(javacore.xyz格式),它確實(shí)揭示了以下Java線程死鎖情況:
死鎖情況可以按照以下方式進(jìn)行翻譯:
– Weblogic線程8正在等待獲取Weblogic線程10擁有的對象監(jiān)視器鎖
– Weblogic線程#10正在等待獲取Weblogic線程#8擁有的對象監(jiān)視器鎖 結(jié)論: Weblogic線程#8和#10都在等待。 永遠(yuǎn)! 現(xiàn)在,在深入分析根本原因之前,讓我為您提供有關(guān)Java Thread死鎖的高級概述。
Java線程死鎖概述
你們大多數(shù)人可能都熟悉Java Thread死鎖原理,但是您真的遇到了真正的死鎖問題嗎?
根據(jù)我的經(jīng)驗(yàn),真正的Java死鎖很少見,并且在過去的10年中,我僅見過約5次此類事件。 原因是大多數(shù)與線程卡住有關(guān)的問題是由于線程掛起情況(正在等待遠(yuǎn)程IO調(diào)用等)引起的,而不是與其他線程發(fā)生真正的死鎖情況。
Java線程死鎖是一種情況,例如,線程A正在等待獲取線程B持有的對象監(jiān)視器鎖定,而線程B本身正在等待獲取線程A持有的對象監(jiān)視器鎖定。這兩個(gè)線程將永遠(yuǎn)彼此等待。 這種情況可以如下圖所示:
線程死鎖已確認(rèn)……現(xiàn)在該怎么辦?
一旦確認(rèn)了死鎖( 大多數(shù)JVM Thread Dump實(shí)現(xiàn)將為您突出顯示 ),下一步就是通過檢查死鎖情況下涉及的每個(gè)線程及其當(dāng)前任務(wù)和等待條件,來進(jìn)行更深入的分析。
在我們的問題案例中,對于涉及死鎖條件的每個(gè)線程,在部分線程堆棧跟蹤下面找到: **請注意,出于保密目的,真實(shí)應(yīng)用程序Java包名稱已重命名**
Weblogic線程#8
'[STUCK] ExecuteThread: '8' for queue: 'weblogic.kernel.Default (self-tuning)'' J9VMThread:0x000000012CC08B00, j9thread_t:0x00000001299E5100, java/lang/Thread:0x070000001D72EE00, state:B, prio=1(native thread ID:0x111200F, native priority:0x1, native policy:UNKNOWN)Java callstack:at weblogic/jms/frontend/FEConnection.stop(FEConnection.java:671(Compiled Code))at weblogic/jms/frontend/FEConnection.invoke(FEConnection.java:1685(Compiled Code))at weblogic/messaging/dispatcher/Request.wrappedFiniteStateMachine(Request.java:961(Compiled Code))at weblogic/messaging/dispatcher/DispatcherImpl.syncRequest(DispatcherImpl.java:184(Compiled Code))at weblogic/messaging/dispatcher/DispatcherImpl.dispatchSync(DispatcherImpl.java:212(Compiled Code))at weblogic/jms/dispatcher/DispatcherAdapter.dispatchSync(DispatcherAdapter.java:43(Compiled Code))at weblogic/jms/client/JMSConnection.stop(JMSConnection.java:863(Compiled Code))at weblogic/jms/client/WLConnectionImpl.stop(WLConnectionImpl.java:843)at org/springframework/jms/connection/SingleConnectionFactory.closeConnection(SingleConnectionFactory.java:342)at org/springframework/jms/connection/SingleConnectionFactory.resetConnection (SingleConnectionFactory.java:296)at org/app/JMSReceiver.receive()……………………………………………………………………Weblogic線程#10
'[STUCK] ExecuteThread: '10' for queue: 'weblogic.kernel.Default (self-tuning)'' J9VMThread:0x000000012E560500, j9thread_t:0x000000012E35BCE0, java/lang/Thread:0x070000001ECA9200, state:B, prio=1(native thread ID:0x4FA027, native priority:0x1, native policy:UNKNOWN)Java callstack:at weblogic/jms/frontend/FEConnection .getPeerVersion(FEConnection.java:1381(Compiled Code))at weblogic/jms/frontend/FESession.setUpBackEndSession(FESession.java:755(Compiled Code))at weblogic/jms/frontend/FESession.consumerCreate(FESession.java:1025(Compiled Code))at weblogic/jms/frontend/FESession.invoke(FESession.java:2995(Compiled Code))at weblogic/messaging/dispatcher/Request.wrappedFiniteStateMachine(Request.java:961(Compiled Code))at weblogic/messaging/dispatcher/DispatcherImpl.syncRequest(DispatcherImpl.java:184(Compiled Code))at weblogic/messaging/dispatcher/DispatcherImpl.dispatchSync(DispatcherImpl.java:212(Compiled Code))at weblogic/jms/dispatcher/DispatcherAdapter.dispatchSync(DispatcherAdapter.java:43(Compiled Code))at weblogic/jms/client/JMSSession.consumerCreate(JMSSession.java:2982(Compiled Code))at weblogic/jms/client/JMSSession.setupConsumer(JMSSession.java:2749(Compiled Code))at weblogic/jms/client/JMSSession.createConsumer(JMSSession.java:2691(Compiled Code))at weblogic/jms/client/JMSSession.createReceiver(JMSSession.java:2596(Compiled Code))at weblogic/jms/client/WLSessionImpl.createReceiver(WLSessionImpl.java:991(Compiled Code))at org/springframework/jms/core/JmsTemplate102.createConsumer(JmsTemplate102.java:204(Compiled Code))at org/springframework/jms/core/JmsTemplate.doReceive(JmsTemplate.java:676(Compiled Code))at org/springframework/jms/core/JmsTemplate$10.doInJms(JmsTemplate.java:652(Compiled Code))at org/springframework/jms/core/JmsTemplate.execute(JmsTemplate.java:412(Compiled Code))at org/springframework/jms/core/JmsTemplate.receiveSelected(JmsTemplate.java:650(Compiled Code))at org/springframework/jms/core/JmsTemplate.receiveSelected(JmsTemplate.java:641(Compiled Code))at org/app/JMSReceiver.receive()…………………………………………………………… 正如您在上面的Thread Strack跟蹤中看到的那樣,這種死鎖確實(shí)來自我們的應(yīng)用程序代碼,該應(yīng)用程序代碼使用Spring框架API進(jìn)行JMS使用者實(shí)現(xiàn)(在不使用MDB的情況下非常有用)。 堆棧跟蹤非常有趣,它揭示了兩個(gè)線程都在同一個(gè) Weblogic JMS使用者會話/連接的競爭狀態(tài)下,并導(dǎo)致死鎖情況:
– Weblogic線程#8試圖重置并關(guān)閉當(dāng)前的JMS連接– Weblogic線程#10試圖使用相同的JMS連接/會話以創(chuàng)建新的JMS使用者–觸發(fā)了線程死鎖!
根本原因:非線程安全的Spring JMS SingleConnectionFactory實(shí)現(xiàn)
Spring JIRA錯(cuò)誤數(shù)據(jù)庫的代碼回顧和快速研究確實(shí)揭示了以下與以下分析完美相關(guān)的以下線程安全缺陷:
#SingleConnectionFactory的resetConnection導(dǎo)致與基礎(chǔ)OracleAQ的JMS連接的死鎖https://jira.springsource.org/browse/SPR-5987
Spring SingleConnectionFactory的補(bǔ)丁發(fā)布于2009年,確實(shí)涉及添加適當(dāng)?shù)膕ync {}塊,以防止在發(fā)生JMS Connection重置操作時(shí)線程死鎖:
解
我們的團(tuán)隊(duì)目前正計(jì)劃將該Spring補(bǔ)丁不久后集成到我們的生產(chǎn)環(huán)境中。 在我們的測試環(huán)境中執(zhí)行的初始測試是肯定的。
結(jié)論
我希望這個(gè)案例研究能夠幫助您理解現(xiàn)實(shí)中的Java Thread死鎖問題,以及適當(dāng)?shù)腡hread Dump分析技能如何使您能夠在代碼級快速查明與線程相關(guān)的問題。 請不要猶豫,發(fā)表任何評論或問題。
參考: Java線程死鎖– Java EE支持模式和Java教程博客上的JCG合作伙伴 Pierre-Hugues Charbonneau的案例研究 。
翻譯自: https://www.javacodegeeks.com/2012/06/java-thread-deadlock-case-study.html
java線程死鎖
總結(jié)
以上是生活随笔為你收集整理的java线程死锁_Java线程死锁–案例研究的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 清洁责任–摆脱均等,compareTo和
- 下一篇: java btrace_BTrace f