Object.wait() 和 LockSupport.park()的實現原理

Object.wait()

在進行wait()以前,就表明着須要爭奪Synchorized,而Synchronized代碼塊經過javap生成的字節碼中包含monitorenter和monitorexit兩個指令。
當在進加鎖的時候會執行monitorenter指令,執行該指令能夠獲取對象的monitor。
同時在執行Lock.wait()的時候也必須持有monitor對象。java

LockSupport.park()

操做對象

歸根結底,LockSupport調用的Unsafe中的native代碼:web

public native void unpark(Thread jthread); 
public native void park(boolean isAbsolute, long time);

兩個函數聲明清楚地說明了操做對象:函數

park函數是將當前Thread阻塞,而unpark函數則是將另外一個Thread喚醒。線程

與Object類的wait/notify機制相比,park/unpark有兩個優勢:設計

  1. 以thread爲操做對象更符合阻塞線程的直觀定義;
  2. 操做更精準,能夠準確地喚醒某一個線程(notify隨機喚醒一個線程,notifyAll喚醒全部等待的線程),增長了靈活性。

關於許可

在上面的文字中,我使用了阻塞和喚醒,是爲了和wait/notify作對比。
其實park/unpark的設計原理核心是「許可」。
park是等待一個許可。
unpark是爲某線程提供一個許可。
若是某線程A調用park,那麼除非另一個線程調用unpark(A)給A一個許可,不然線程A將阻塞在park操做上。code

有一點比較難理解的,是unpark操做能夠再park操做以前。
也就是說,先提供許可。當某線程調用park時,已經有許可了,它就消費這個許可,而後能夠繼續運行。
這實際上是必須的。對象

考慮最簡單的生產者(Producer)消費者(Consumer)模型:資源

Consumer須要消費一個資源,因而調用park操做等待;get

Producer則生產資源,而後調用unpark給予Consumer使用的許可。it

很是有可能的一種狀況是,Producer先生產,這時候Consumer可能尚未構造好(好比線程還沒啓動,或者還沒切換到該線程)。
那麼等Consumer準備好要消費時,顯然這時候資源已經生產好了,能夠直接用,那麼park操做固然能夠直接運行下去。
若是沒有這個語義,那將很是難以操做。

本文由猿必過 YBG 發佈
相關文章
相關標籤/搜索