Java线程阻塞原语-LockSupport
在Java6引入LockSupport以前,線程掛起和喚醒要通過Object的wait和notify/notifyAllfangAll實現,但后者必須要在同步塊里調用,且notify必須要在wait之后調用才行否則會導致線程阻塞。
LockSupport比Object的wait/notify有兩大優勢:
LockSupport原理
LockSupport和每個使用它的線程都與一個許可(permit)關聯。permit類似信號量,相當于1,0的開關,默認是0(表示許可是被占用的,調用park()會阻塞),調用一次unpark被置為1,調用一次park會消費permit, 也就是將1變成0,同時park立即返回。再次調用park會變成block(因為permit為0了,會阻塞在這里,直到permit變為1), 這時調用unpark會把permit置為1。每個線程都有一個相關的permit, permit最多只有一個,重復調用unpark也不會積累。
park()和unpark()不會有 “Thread.suspend和Thread.resume所可能引發的死鎖” 問題,由于許可的存在,調用 park 的線程和另一個試圖將其 unpark 的線程之間的競爭將保持活性
許可默認是占用的
public static void main(String[] args)
{
?? LockSupport.park();????? //此處阻塞,因為許可默認占用。
?? System.out.println("block.");
}
?
public static void main(String[] args)
{
?? Thread thread = Thread.currentThread();
?? LockSupport.unpark(thread);????????? //釋放許可
?? LockSupport.park();??????????????????????? // 獲取許可,此處不阻塞,繼續運行
?? System.out.println("b");
}
?
LockSupport不可重入
public static void main(String[] args) throws Exception
{
?Thread thread = Thread.currentThread();
?
?LockSupport.unpark(thread);? //釋放許可
?
?System.out.println("a");
?LockSupport.park();?????????????? // 獲取許可,此處不阻塞,繼續運行
?System.out.println("b");
?LockSupport.park();????????????? // 獲取不到許可,此處阻塞
?System.out.println("c");?
}
對中斷的響應
線程如果因為調用park而阻塞的話,能夠響應中斷請求,park()方法返回(不再阻塞),中斷狀態被設置成true,但是不會拋出InterruptedException。
LockSupport函數列表
// 返回提供給最近一次尚未解除阻塞的 park 方法調用的 blocker 對象,如果該調用不受阻塞,則返回 null。 static Object getBlocker(Thread t) // 為了線程調度,禁用當前線程,除非許可可用。 static void park() // 為了線程調度,在許可可用之前禁用當前線程。 static void park(Object blocker) // 為了線程調度禁用當前線程,最多等待指定的等待時間,除非許可可用。 static void parkNanos(long nanos) // 為了線程調度,在許可可用前禁用當前線程,并最多等待指定的等待時間。 static void parkNanos(Object blocker, long nanos) // 為了線程調度,在指定的時限前禁用當前線程,除非許可可用。 static void parkUntil(long deadline) // 為了線程調度,在指定的時限前禁用當前線程,除非許可可用。 static void parkUntil(Object blocker, long deadline) // 如果給定線程的許可尚不可用,則使其可用。(釋放許可) static void unpark(Thread thread)blocker:這個對象是用來記錄線程被阻塞時被誰阻塞的。
相對時間與絕對時間:
LockSupport的park()函數調用了unsafe.park()方法。
public static void park() {unsafe.park(false, 0L);}public static void parkNanos(long nanos) {if (nanos > 0)unsafe.park(false, nanos);}public static void parkUntil(long deadline) {unsafe.park(true, deadline);} //Unsafe public native void park(boolean isAbsolute, long time);-
nanos:在nanos時間后線程自動恢復掛起
-
deadline:在deadline時刻線程自動(這個毫秒其實就是自1970年1月1日0時起的毫秒數)
park方法是一個阻塞的方法,除非4個條件
當配對的unpark發生
線程被中斷時恢復
阻塞時間已過
- 當absolute是false時,如果給定的時間是非0(負數)或者給定的時間(正數, 時間單位時毫秒)已經過去了(0的時候會一直阻塞著)。
- 當Absolute是true時,如果給定的時間(時間單位是納秒)過去了或者偽造的(在我理解是參數不合法時)線程會恢復中斷。
?
?
?
?
?
?
總結
以上是生活随笔為你收集整理的Java线程阻塞原语-LockSupport的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java反射-继承关系
- 下一篇: AbstractQueuedSynchr