目錄
一、產(chǎn)生死鎖的原因
發(fā)生死鎖的情況: 多個線程需要同時占用多個共享資源而發(fā)生需要互相死循環(huán)等待的情況,就是,兩個線程互相等待著對象釋放鎖,一直這樣僵持下去,所以導致了死鎖的產(chǎn)生。
產(chǎn)生死鎖代碼:
package com
. javaagent
. thread
; public class DieThread implements Runnable { public static Object obj1
= new Object ( ) ; public static Object obj2
= new Object ( ) ; private boolean flag
; public DieThread ( boolean bl
) { flag
= bl
; } @Override public void run ( ) { if ( flag
) { while ( true ) { synchronized ( obj1
) { try { Thread
. sleep ( 1000 ) ; } catch ( InterruptedException e
) { e
. printStackTrace ( ) ; } System
. out
. println ( "線程" + Thread
. currentThread ( ) . getName ( ) + "獲取obj1鎖對象,等待獲取obj2鎖對象..." ) ; synchronized ( obj2
) { System
. out
. println ( Thread
. currentThread ( ) . getName ( ) + " ---- obj2." ) ; } } } } else { while ( true ) { synchronized ( obj2
) { System
. out
. println ( "線程" + Thread
. currentThread ( ) . getName ( ) + "獲取obj2鎖對象,等待獲取obj1鎖對象..." ) ; synchronized ( obj1
) { System
. out
. println ( Thread
. currentThread ( ) . getName ( ) + " ---- obj1." ) ; } } } } }
}
public class Main { public static void main ( String
[ ] args
) { DieThread d1
= new DieThread ( true ) ; DieThread d2
= new DieThread ( false ) ; final Thread t1
= new Thread ( d1
) ; final Thread t2
= new Thread ( d2
) ; t1
. setName ( "DieThread_1" ) ; t2
. setName ( "DieThread_2" ) ; t1
. start ( ) ; t2
. start ( ) ; }
}
輸出結(jié)果:
線程DieThread_2獲取obj2鎖對象,等待獲取obj1鎖對象
. . .
線程DieThread_1獲取obj1鎖對象,等待獲取obj2鎖對象
. . .
采用 visualVM工具 來進行診斷,結(jié)果如下圖所示: 從該圖中,我們可以看出,Main的 進程ID為84114 ,紅框1中提示 檢測到死鎖 ,然后我們點擊紅框3來查看 線程Dump 數(shù)據(jù),如下圖: 詳細信息:
2020 - 03 - 04 15 : 02 : 44
Full thread dump Java
HotSpot ( TM
) 64 - Bit Server VM
( 25.121 - b13 mixed mode
) : "RMI TCP Connection(idle)" #
19 daemon prio
= 9 os_prio
= 31 tid
= 0x00007ff1db108800 nid
= 0x5f03 waiting on condition
[ 0x0000700001961000 ] java
. lang
. Thread
. State
: TIMED_WAITING
( parking
) at sun
. misc
. Unsafe
. park ( Native Method
) - parking to wait
for < 0x0000000796082e28> ( a java
. util
. concurrent
. SynchronousQueue$TransferStack
) at java
. util
. concurrent
. locks
. LockSupport
. parkNanos ( LockSupport
. java
: 215 ) at java
. util
. concurrent
. SynchronousQueue$TransferStack
. awaitFulfill ( SynchronousQueue
. java
: 460 ) at java
. util
. concurrent
. SynchronousQueue$TransferStack
. transfer ( SynchronousQueue
. java
: 362 ) at java
. util
. concurrent
. SynchronousQueue
. poll ( SynchronousQueue
. java
: 941 ) at java
. util
. concurrent
. ThreadPoolExecutor
. getTask ( ThreadPoolExecutor
. java
: 1066 ) at java
. util
. concurrent
. ThreadPoolExecutor
. runWorker ( ThreadPoolExecutor
. java
: 1127 ) at java
. util
. concurrent
. ThreadPoolExecutor$Worker
. run ( ThreadPoolExecutor
. java
: 617 ) at java
. lang
. Thread
. run ( Thread
. java
: 745 ) Locked ownable synchronizers
: - None
"JMX server connection timeout 18" #
18 daemon prio
= 9 os_prio
= 31 tid
= 0x00007ff1da87c800 nid
= 0x5d03 in Object
. wait ( ) [ 0x000070000185e000 ] java
. lang
. Thread
. State
: TIMED_WAITING
( on object monitor
) at java
. lang
. Object
. wait ( Native Method
) at com
. sun
. jmx
. remote
. internal
. ServerCommunicatorAdmin$Timeout
. run ( ServerCommunicatorAdmin
. java
: 168 ) - locked
< 0x00000007964a9dc8> ( a
[ I
) at java
. lang
. Thread
. run ( Thread
. java
: 745 ) Locked ownable synchronizers
: - None
"RMI Scheduler(0)" #
17 daemon prio
= 9 os_prio
= 31 tid
= 0x00007ff1da895800 nid
= 0x5b03 waiting on condition
[ 0x000070000175b000 ] java
. lang
. Thread
. State
: TIMED_WAITING
( parking
) at sun
. misc
. Unsafe
. park ( Native Method
) - parking to wait
for < 0x00000007960ab5d8> ( a java
. util
. concurrent
. locks
. AbstractQueuedSynchronizer$ConditionObject
) at java
. util
. concurrent
. locks
. LockSupport
. parkNanos ( LockSupport
. java
: 215 ) at java
. util
. concurrent
. locks
. AbstractQueuedSynchronizer$ConditionObject
. awaitNanos ( AbstractQueuedSynchronizer
. java
: 2078 ) at java
. util
. concurrent
. ScheduledThreadPoolExecutor$DelayedWorkQueue
. take ( ScheduledThreadPoolExecutor
. java
: 1093 ) at java
. util
. concurrent
. ScheduledThreadPoolExecutor$DelayedWorkQueue
. take ( ScheduledThreadPoolExecutor
. java
: 809 ) at java
. util
. concurrent
. ThreadPoolExecutor
. getTask ( ThreadPoolExecutor
. java
: 1067 ) at java
. util
. concurrent
. ThreadPoolExecutor
. runWorker ( ThreadPoolExecutor
. java
: 1127 ) at java
. util
. concurrent
. ThreadPoolExecutor$Worker
. run ( ThreadPoolExecutor
. java
: 617 ) at java
. lang
. Thread
. run ( Thread
. java
: 745 ) Locked ownable synchronizers
: - None
"RMI TCP Connection(1)-10.0.5.39" #
16 daemon prio
= 9 os_prio
= 31 tid
= 0x00007ff1d99ed800 nid
= 0x5903 runnable
[ 0x0000700001657000 ] java
. lang
. Thread
. State
: RUNNABLEat 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 java
. io
. BufferedInputStream
. fill ( BufferedInputStream
. java
: 246 ) at java
. io
. BufferedInputStream
. read ( BufferedInputStream
. java
: 265 ) - locked
< 0x00000007963eced8> ( a java
. io
. BufferedInputStream
) at java
. io
. FilterInputStream
. read ( FilterInputStream
. java
: 83 ) at sun
. rmi
. transport
. tcp
. TCPTransport
. handleMessages ( TCPTransport
. java
: 550 ) at sun
. rmi
. transport
. tcp
. TCPTransport$ConnectionHandler
. run0 ( TCPTransport
. java
: 826 ) at sun
. rmi
. transport
. tcp
. TCPTransport$ConnectionHandler
. lambda$run$
0 ( TCPTransport
. java
: 683 ) at sun
. rmi
. transport
. tcp
. TCPTransport$ConnectionHandler$$Lambda$
3 / 657644190. run ( Unknown Source
) at java
. security
. AccessController
. doPrivileged ( Native Method
) at sun
. rmi
. transport
. tcp
. TCPTransport$ConnectionHandler
. run ( TCPTransport
. java
: 682 ) at java
. util
. concurrent
. ThreadPoolExecutor
. runWorker ( ThreadPoolExecutor
. java
: 1142 ) at java
. util
. concurrent
. ThreadPoolExecutor$Worker
. run ( ThreadPoolExecutor
. java
: 617 ) at java
. lang
. Thread
. run ( Thread
. java
: 745 ) Locked ownable synchronizers
: - < 0x0000000796299c10> ( a java
. util
. concurrent
. ThreadPoolExecutor$Worker
) "RMI TCP Accept-0" #
15 daemon prio
= 9 os_prio
= 31 tid
= 0x00007ff1d9941800 nid
= 0x570f runnable
[ 0x0000700001555000 ] java
. lang
. Thread
. State
: RUNNABLEat java
. net
. PlainSocketImpl
. socketAccept ( Native Method
) at java
. net
. AbstractPlainSocketImpl
. accept ( AbstractPlainSocketImpl
. java
: 409 ) at java
. net
. ServerSocket
. implAccept ( ServerSocket
. java
: 545 ) at java
. net
. ServerSocket
. accept ( ServerSocket
. java
: 513 ) at sun
. management
. jmxremote
. LocalRMIServerSocketFactory$
1. accept ( LocalRMIServerSocketFactory
. java
: 52 ) at sun
. rmi
. transport
. tcp
. TCPTransport$AcceptLoop
. executeAcceptLoop ( TCPTransport
. java
: 400 ) at sun
. rmi
. transport
. tcp
. TCPTransport$AcceptLoop
. run ( TCPTransport
. java
: 372 ) at java
. lang
. Thread
. run ( Thread
. java
: 745 ) Locked ownable synchronizers
: - None
"Attach Listener" #
13 daemon prio
= 9 os_prio
= 31 tid
= 0x00007ff1db028800 nid
= 0x5303 waiting on condition
[ 0x0000000000000000 ] java
. lang
. Thread
. State
: RUNNABLELocked ownable synchronizers
: - None
"DestroyJavaVM" #
12 prio
= 5 os_prio
= 31 tid
= 0x00007ff1da1ac000 nid
= 0x1403 waiting on condition
[ 0x0000000000000000 ] java
. lang
. Thread
. State
: RUNNABLELocked ownable synchronizers
: - None
"DieThread_2" #
11 prio
= 5 os_prio
= 31 tid
= 0x00007ff1d9839800 nid
= 0x5103 waiting
for monitor entry
[ 0x000070000134f000 ] java
. lang
. Thread
. State
: BLOCKED
( on object monitor
) at com
. javaagent
. thread
. DieThread
. run ( DieThread
. java
: 37 ) - waiting to lock
< 0x000000079585bee0> ( a java
. lang
. Object
) - locked
< 0x000000079585bef0> ( a java
. lang
. Object
) at java
. lang
. Thread
. run ( Thread
. java
: 745 ) Locked ownable synchronizers
: - None
"DieThread_1" #
10 prio
= 5 os_prio
= 31 tid
= 0x00007ff1d9835800 nid
= 0x4f03 waiting
for monitor entry
[ 0x000070000124c000 ] java
. lang
. Thread
. State
: BLOCKED
( on object monitor
) at com
. javaagent
. thread
. DieThread
. run ( DieThread
. java
: 26 ) - waiting to lock
< 0x000000079585bef0> ( a java
. lang
. Object
) - locked
< 0x000000079585bee0> ( a java
. lang
. Object
) at java
. lang
. Thread
. run ( Thread
. java
: 745 ) Locked ownable synchronizers
: - None
"Service Thread" #
9 daemon prio
= 9 os_prio
= 31 tid
= 0x00007ff1d9835000 nid
= 0x4b03 runnable
[ 0x0000000000000000 ] java
. lang
. Thread
. State
: RUNNABLELocked ownable synchronizers
: - None
"C1 CompilerThread2" #
8 daemon prio
= 9 os_prio
= 31 tid
= 0x00007ff1da87f800 nid
= 0x4903 waiting on condition
[ 0x0000000000000000 ] java
. lang
. Thread
. State
: RUNNABLELocked ownable synchronizers
: - None
"C2 CompilerThread1" #
7 daemon prio
= 9 os_prio
= 31 tid
= 0x00007ff1d98c5800 nid
= 0x4703 waiting on condition
[ 0x0000000000000000 ] java
. lang
. Thread
. State
: RUNNABLELocked ownable synchronizers
: - None
"C2 CompilerThread0" #
6 daemon prio
= 9 os_prio
= 31 tid
= 0x00007ff1da886000 nid
= 0x4503 waiting on condition
[ 0x0000000000000000 ] java
. lang
. Thread
. State
: RUNNABLELocked ownable synchronizers
: - None
"Monitor Ctrl-Break" #
5 daemon prio
= 5 os_prio
= 31 tid
= 0x00007ff1da884800 nid
= 0x4303 runnable
[ 0x0000700000c3a000 ] java
. lang
. Thread
. State
: RUNNABLEat 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
< 0x00000007958fc840> ( 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
< 0x00000007958fc840> ( a java
. io
. InputStreamReader
) at java
. io
. BufferedReader
. readLine ( BufferedReader
. java
: 389 ) at com
. intellij
. rt
. execution
. application
. AppMainV2$
1. run ( AppMainV2
. java
: 64 ) Locked ownable synchronizers
: - None
"Signal Dispatcher" #
4 daemon prio
= 9 os_prio
= 31 tid
= 0x00007ff1db029800 nid
= 0x360f runnable
[ 0x0000000000000000 ] java
. lang
. Thread
. State
: RUNNABLELocked ownable synchronizers
: - None
"Finalizer" #
3 daemon prio
= 8 os_prio
= 31 tid
= 0x00007ff1d9820800 nid
= 0x3003 in Object
. wait ( ) [ 0x000070000092e000 ] java
. lang
. Thread
. State
: WAITING
( on object monitor
) at java
. lang
. Object
. wait ( Native Method
) - waiting on
< 0x0000000795588ec8> ( a java
. lang
. ref
. ReferenceQueue$Lock
) at java
. lang
. ref
. ReferenceQueue
. remove ( ReferenceQueue
. java
: 143 ) - locked
< 0x0000000795588ec8> ( a java
. lang
. ref
. ReferenceQueue$Lock
) at java
. lang
. ref
. ReferenceQueue
. remove ( ReferenceQueue
. java
: 164 ) at java
. lang
. ref
. Finalizer$FinalizerThread
. run ( Finalizer
. java
: 209 ) Locked ownable synchronizers
: - None
"Reference Handler" #
2 daemon prio
= 10 os_prio
= 31 tid
= 0x00007ff1d9810800 nid
= 0x2e03 in Object
. wait ( ) [ 0x000070000082b000 ] java
. lang
. Thread
. State
: WAITING
( on object monitor
) at java
. lang
. Object
. wait ( Native Method
) - waiting on
< 0x0000000795586b68> ( a java
. lang
. ref
. Reference$Lock
) at java
. lang
. Object
. wait ( Object
. java
: 502 ) at java
. lang
. ref
. Reference
. tryHandlePending ( Reference
. java
: 191 ) - locked
< 0x0000000795586b68> ( a java
. lang
. ref
. Reference$Lock
) at java
. lang
. ref
. Reference$ReferenceHandler
. run ( Reference
. java
: 153 ) Locked ownable synchronizers
: - None
"VM Thread" os_prio
= 31 tid
= 0x00007ff1da026800 nid
= 0x2c03 runnable
"GC task thread#0 (ParallelGC)" os_prio
= 31 tid
= 0x00007ff1d9810000 nid
= 0x2403 runnable
"GC task thread#1 (ParallelGC)" os_prio
= 31 tid
= 0x00007ff1da00d000 nid
= 0x2603 runnable
"GC task thread#2 (ParallelGC)" os_prio
= 31 tid
= 0x00007ff1da00d800 nid
= 0x2803 runnable
"GC task thread#3 (ParallelGC)" os_prio
= 31 tid
= 0x00007ff1da00e000 nid
= 0x2a03 runnable
"VM Periodic Task Thread" os_prio
= 31 tid
= 0x00007ff1da80d000 nid
= 0x4d03 waiting on condition JNI global references
: 354 Found one Java
- level deadlock
:
== == == == == == == == == == == == == == =
"DieThread_2" : waiting to lock monitor
0x00007ff1da80ad58 ( object
0x000000079585bee0 , a java
. lang
. Object
) , which is held by
"DieThread_1"
"DieThread_1" : waiting to lock monitor
0x00007ff1da808418 ( object
0x000000079585bef0 , a java
. lang
. Object
) , which is held by
"DieThread_2" Java stack information
for the threads listed above
:
== == == == == == == == == == == == == == == == == == == == == == == == == =
"DieThread_2" : at com
. javaagent
. thread
. DieThread
. run ( DieThread
. java
: 37 ) - waiting to lock
< 0x000000079585bee0> ( a java
. lang
. Object
) - locked
< 0x000000079585bef0> ( a java
. lang
. Object
) at java
. lang
. Thread
. run ( Thread
. java
: 745 )
"DieThread_1" : at com
. javaagent
. thread
. DieThread
. run ( DieThread
. java
: 26 ) - waiting to lock
< 0x000000079585bef0> ( a java
. lang
. Object
) - locked
< 0x000000079585bee0> ( a java
. lang
. Object
) at java
. lang
. Thread
. run ( Thread
. java
: 745 ) Found
1 deadlock
.
通過上面的線程Dump文件信息,我們可以看出來發(fā)生了死鎖,下面也列出了java級別的鎖問題和棧信息:
Found one Java
- level deadlock
:
== == == == == == == == == == == == == == =
"DieThread_2" : waiting to lock monitor
0x00007ff1da80ad58 ( object
0x000000079585bee0 , a java
. lang
. Object
) , which is held by
"DieThread_1"
"DieThread_1" : waiting to lock monitor
0x00007ff1da808418 ( object
0x000000079585bef0 , a java
. lang
. Object
) , which is held by
"DieThread_2" Java stack information
for the threads listed above
:
== == == == == == == == == == == == == == == == == == == == == == == == == =
"DieThread_2" : at com
. javaagent
. thread
. DieThread
. run ( DieThread
. java
: 37 ) - waiting to lock
< 0x000000079585bee0> ( a java
. lang
. Object
) - locked
< 0x000000079585bef0> ( a java
. lang
. Object
) at java
. lang
. Thread
. run ( Thread
. java
: 745 )
"DieThread_1" : at com
. javaagent
. thread
. DieThread
. run ( DieThread
. java
: 26 ) - waiting to lock
< 0x000000079585bef0> ( a java
. lang
. Object
) - locked
< 0x000000079585bee0> ( a java
. lang
. Object
) at java
. lang
. Thread
. run ( Thread
. java
: 745 ) Found
1 deadlock
.
并且棧信息中,可以定位到死鎖發(fā)生的地方。
如果解決死鎖,那是因為代碼的邏輯存在問題,可以調(diào)整代碼的邏輯或者業(yè)務(wù),來避免死鎖。
二、如何避免死鎖
避免一個線程同時獲取多個鎖
避免一個線程在鎖內(nèi)同時占用多個資源,盡量保證每個鎖只占用一個資源
嘗試使用定時鎖,使用 lock.tryLock(timeout) 來替代使用內(nèi)部鎖機制。
對于數(shù)據(jù)庫鎖,加鎖和解鎖必須在一個數(shù)據(jù)庫連接里,否則會出現(xiàn)解鎖失敗的情況。
總結(jié)
以上是生活随笔 為你收集整理的Java多线程死锁例子 的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔 推薦給好友。