java執行緒棧狀態詳解

朱清震發表於2018-02-10

在到處java執行緒棧的時候,會看到執行緒棧第一行最後都有一個狀態說明,下面就說一下這幾種狀態是什麼情況下出現的,理解java執行緒棧對於分析問題非常有幫助;

       /**
* 一. waiting for monitor entry

* BLOCKED (on object monitor)
* 等待進入synchronized臨界區

* 二. in Object.wait()
* 1. TIMED_WAITING (on object monitor)
* 執行了java.lang.Object.wait(timeout)(Native Method)方法

* 2. WAITING (on object monitor)
* 執行了java.lang.Object.wait(Native Method)方法


* 三. waiting on condition

* 1.TIMED_WAITING (sleeping)
* java.lang.Thread.sleep(Native Method)

* 2.TIMED_WAITING (parking)
* sun.misc.UNSAFE.park(false, nanos);
* java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)

* 3.WAITING (parking)
* sun.misc.UNSAFE.park(false, 0L);
* java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)

* 4. RUNNABLE 特殊情況
* 很多本地執行緒處於此狀態

* 四. runnable

* 1.RUNNABLE
* 正在jvm內執行的執行緒

* 2.RUNNABLE 特殊情況
* 正在執行本地方法的執行緒,jvm獲取不到其狀態,可能是阻塞狀態;

* @author zqz
*
*/

下面相機


waiting on condition 


這種狀態三種子狀態:

 一、TIMED_WAITING (sleeping)

當呼叫了Thread.sleep()方法時會進入這種狀態,執行緒棧如下:

java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(Native Method)

需要注意的是,如果執行緒持有鎖,則不會釋放鎖; 

 二、TIMED_WAITING (parking)

    sun.misc.UNSAFE.park(false, nanos);

     java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)

 

 三、WAITING (parking)

 sun.misc.UNSAFE.park(false, 0L);
 java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)

有以下幾種情況會進入WAITING(parking)狀態

  •  LockSupport.park() 

java.lang.Thread.State: WAITING (parking)

at sun.misc.Unsafe.park(Native Method)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:304)

直接在我們應用中呼叫了LockSupport.park()方法,沒有引數,將當前執行緒阻塞;

  • LockSupport.park(Object)

   呼叫該方法有以下三種場景

1)ReentrantLock.lock()方法

java.lang.Thread.State: WAITING (parking)

at sun.misc.Unsafe.park(Native Method)
- parking to wait for  <0x00000000d62762c0> (a java.util.concurrent.locks.ReentrantLock$NonfairSync)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:836)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:870)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1199)
at java.util.concurrent.locks.ReentrantLock$NonfairSync.lock(ReentrantLock.java:209)
at java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:285)


這裡是呼叫了可重入鎖的lock方法,可重入鎖最終是呼叫了LockSuport.park(Object)方法將執行緒阻塞的,與無參的LockSupport.Park()方法的呼叫棧是不一樣的;

2)RetreenLock.newCondition().await()


 java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for  <0x00000000d6276400> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)

at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)

呼叫了RetreenLock.newCondition().await()方法,最終呼叫的也是LockSupport.park(Object)方法;

3)在應用中直接呼叫Locksupport.park(Object)方法

呼叫棧參考上面兩個,這裡就不列出來了


上面三種是一樣的,列出前兩種的目的是為了讓大家清楚,當呼叫棧像給出的那樣時,我們呼叫了哪些java哪些內建的方法間接呼叫的LockeSupprot.park(Object)方法;




  四、 runnable

特殊情況,這種狀態不一致的情況也會出現,處於此狀態的執行緒正在執行本地方法,應該算是jvm中的一個bug;



waiting for monitor entry

這種狀態的執行緒只有一種子狀態:BLOCKED (on object monitor)

 java.lang.Thread.State: BLOCKED (on object monitor)
at com.zqz.test.threadstate.ThreadStateTest$Monitor_EntrySet.Monitor_EntrySet_run(ThreadStateTest.java:137)
- waiting to lock <0x00000000d6274fa0> (a java.lang.Boolean)

執行緒進入synchronized同步塊之前,因為已經有其它執行緒進入同步塊了,所以當先執行緒被阻塞在EntrySet佇列中等待進入synchronized程式碼塊;


in Object.wait()

這種狀態的執行緒有兩種子狀態:

 1. TIMED_WAITING (on object monitor)

 執行了java.lang.Object.wait(timeout)(Native Method)方法,帶有是時間

  2. WAITING (on object monitor)

 執行了java.lang.Object.wait(Native Method)方法


 java.lang.Thread.State: WAITING (on object monitor)

at java.lang.Object.wait(Native Method)
- waiting on <0x00000000d6274fa0> (a java.lang.Boolean)
at java.lang.Object.wait(Object.java:502)
at com.zqz.test.threadstate.ThreadStateTest$Monitor_WaitSet.Monitor_WaitSet_run(ThreadStateTest.java:157)
- locked <0x00000000d6274fa0> (a java.lang.Boolean)


處於這種狀態的執行緒,執行緒棧首先會有一個locked動作,說明其應進入到了synchronized程式碼塊,在程式碼快中由於某些條件不滿足,無法繼續執行,又做了Object.Wait()操作釋放鎖進入等待狀態;



runnable



 java.lang.Thread.State: RUNNABLE

java執行緒正在執行,需要注意的是這種執行緒如果在執行本地方法,而本地方法阻塞了執行緒,雖然執行緒處於阻塞狀態,但是java執行緒獲取不到本地方法執行的狀態,這時仍然顯示runnable;



  • Thread.sleep()
java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(Native Method)


執行緒執行了sleep方法,需要注意的是,如果執行緒持有鎖,則不會釋放鎖;



鎖與執行緒棧的關係

Synchronized鎖

來看下0x00000007d616a0c8鎖的執行過程:

一、執行緒WaitSet--locked--waiting on--in Object.wait()1 先執行:

"WaitSet--locked--waiting on--in Object.wait()1" prio=6 tid=0x000000000d9fb800 nid=0x2e3c in Object.wait() [0x000000000e76f000]
   java.lang.Thread.State: WAITING (on object monitor)
	at java.lang.Object.wait(Native Method)
	- waiting on <0x00000007d616a0c8> (a java.lang.Boolean)
	at java.lang.Object.wait(Object.java:503)
	at com.zqz.test.threadstate.ThreadStateTest$Monitor_WaitSet.Monitor_WaitSet_run(ThreadStateTest.java:1525)
	- locked <0x00000007d616a0c8> (a java.lang.Boolean)
	at com.zqz.test.threadstate.ThreadStateTest$Monitor_WaitSet.run(ThreadStateTest.java:1517)

   Locked ownable synchronizers:
	- None


這個執行緒:

1. 執行- locked <0x00000007d616a0c8> (a java.lang.Boolean)  持有了鎖;

2. 執行- waiting on <0x00000007d616a0c8> (a java.lang.Boolean)  執行了Object.wait()釋放了鎖,並進入到wait 佇列;


二、執行緒”locked--sleeping--wait on Condition1“開始執行:

"locked--sleeping--wait on Condition1" prio=6 tid=0x000000000d9fc000 nid=0x142c waiting on condition [0x000000000e8bf000]
   java.lang.Thread.State: TIMED_WAITING (sleeping)
	at java.lang.Thread.sleep(Native Method)
	at com.zqz.test.threadstate.ThreadStateTest$LockedSleeping.LockedSleeping_run(ThreadStateTest.java:1565)
	- locked <0x00000007d616a0d8> (a java.lang.Object)
	- locked <0x00000007d616a0c8> (a java.lang.Boolean)
	at com.zqz.test.threadstate.ThreadStateTest$LockedSleeping.run(ThreadStateTest.java:1547)

   Locked ownable synchronizers:
	- None
這個執行緒在上面執行緒釋放鎖後,它執行 - locked <0x00000007d616a0c8> (a java.lang.Boolean)  持有了鎖;

三、執行緒“EntrySet--waiting to lock---Waiting for monitor entry2”開始執行

"EntrySet--waiting to lock---Waiting for monitor entry2" prio=6 tid=0x000000000da03000 nid=0x383c waiting for monitor entry [0x000000000ebcf000]
   java.lang.Thread.State: BLOCKED (on object monitor)
	at com.zqz.test.threadstate.ThreadStateTest$Monitor_EntrySet.Monitor_EntrySet_run(ThreadStateTest.java:1505)
	- waiting to lock <0x00000007d616a0c8> (a java.lang.Boolean)
	at com.zqz.test.threadstate.ThreadStateTest$Monitor_EntrySet.run(ThreadStateTest.java:1492)

   Locked ownable synchronizers:
	- None

這個執行緒執行後發現鎖已經被別的執行緒持有了,所以執行- waiting to lock <0x00000007d616a0c8> (a java.lang.Boolean) 進入到monitor entry佇列,等待競爭鎖;



ReentrantLock


"RTlock has Lock1" prio=6 tid=0x000000000da2c800 nid=0x3830 waiting on condition [0x000000000ed0f000]
   java.lang.Thread.State: TIMED_WAITING (sleeping)
	at java.lang.Thread.sleep(Native Method)
	at com.zqz.test.threadstate.ThreadStateTest$RTlockLocked.run(ThreadStateTest.java:1445)

   Locked ownable synchronizers:
	- <0x00000007d616a378> (a java.util.concurrent.locks.ReentrantLock$NonfairSync)

Locked ownable synchronizers: 代表當前執行緒持有了0x00000007d616a378鎖

"RTlock wait Lock2" prio=6 tid=0x000000000da34000 nid=0xacc waiting on condition [0x000000000ee9f000]
   java.lang.Thread.State: WAITING (parking)
	at sun.misc.Unsafe.park(Native Method)
	- parking to wait for  <0x00000007d616a378> (a java.util.concurrent.locks.ReentrantLock$NonfairSync)
	at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:834)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:867)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1197)
	at java.util.concurrent.locks.ReentrantLock$NonfairSync.lock(ReentrantLock.java:214)
	at java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:290)
	at com.zqz.test.threadstate.ThreadStateTest$RTlockWaitLocke.run(ThreadStateTest.java:1470)

   Locked ownable synchronizers:
	- None

- parking to wait for  <0x00000007d616a378> (a java.util.concurrent.locks.ReentrantLock$NonfairSync)

代表當前執行緒正在等待0x00000007d616a378鎖


LockSupport.park()鎖


"LockSupportPark2--park1" prio=6 tid=0x000000000d9f6800 nid=0x2a44 waiting on condition [0x000000000e66f000]
   java.lang.Thread.State: WAITING (parking)
	at sun.misc.Unsafe.park(Native Method)
	- parking to wait for  <0x00000007d616e988> (a com.zqz.test.threadstate.ThreadStateTest$LockSupportPark2)
	at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186)
	at com.zqz.test.threadstate.ThreadStateTest$LockSupportPark2.park(ThreadStateTest.java:1610)
	at com.zqz.test.threadstate.ThreadStateTest$LockSupportPark2.parkMethod(ThreadStateTest.java:1605)
	at com.zqz.test.threadstate.ThreadStateTest$LockSupportPark2.run(ThreadStateTest.java:1602)

   Locked ownable synchronizers:
	- None
代表它執行LockSupport.park把自己給阻塞了,需要另外一個執行緒unpark這個執行緒才能繼續執行;這種情況並沒有其它執行緒持有鎖

相關文章