併發程式設計(五)LockSupport
阿新 • • 發佈:2018-12-06
併發程式設計(五)LockSupport
LockSupport 提供 park() 和 unpark() 方法實現阻塞執行緒和解除執行緒阻塞,實現的阻塞和解除阻塞是基於“許可(permit)”作為關聯,permit 相當於一個訊號量(0,1),預設是0。 執行緒之間不再需要一個 Object 或者其它變數來儲存狀態,不再需要關心對方的狀態。
一、LockSupport API
(1) pack
方法 | 說明 |
---|---|
park() | 掛起當前執行緒 |
park(Object blocker) | 掛起當前執行緒 |
parkNanos(long nanos) | 指定掛起時間(相對於當前的時間),時間到後自動被喚醒 |
parkNanos(Object blocker, long nanos) | 指定掛起時間(相對於當前的時間) |
parkUntil(long deadline) | 指定掛起時間(絕對時間),時間到後自動被喚醒 |
parkUntil(Object blocker, long deadline) | 指定掛起時間(絕對時間),時間到後自動被喚醒 |
從上面表格可以看出,park 支援 blocker 物件作為引數,該欄位是 Thread 類,專門為 LockSupport 而設計的。此 blocker 物件線上程受阻塞時被記錄,這樣監視工具和診斷工具就可以確定執行緒受阻塞的原因。建議最好使用這些帶 blocker 的方法版本,而不是不帶 blocker 引數的方法。
public static void park() {
UNSAFE.park(false, 0L);
}
(2) unpark
設定執行緒許可為可用。
- 如果執行緒當前已經被 pack 掛起,那麼這個執行緒將會被喚醒。
- 如果執行緒當前沒有被掛起,那麼下次呼叫 pack 不會掛起執行緒。
public static void unpark(Thread thread) {
if (thread != null)
UNSAFE.unpark(thread);
}
二、LockSupport 使用
(1) 先park後unpark
public void test1() throws Exception { Thread mainThread = Thread.currentThread(); Thread thread = new Thread(() -> { try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } System.out.println("before unpark, " + LockSupport.getBlocker(mainThread)); LockSupport.unpark(mainThread); System.out.println("after unpark, " + LockSupport.getBlocker(mainThread)); }); thread.start(); System.out.println("before park"); // 等待獲取許可 LockSupport.park("Park"); System.out.println("after park"); }
結果:
before park
before unpark, Park
after park
after unpark, null
(2) 先unpark後unpark
先執行 unpark,在呼叫 park,直接就沒被阻塞, 因此 park/unpark 相比 wait/notify 更加的靈活
public void test2() throws Exception {
Thread mainThread = Thread.currentThread();
Thread thread = new Thread(() -> {
System.out.println("before unpark, " + LockSupport.getBlocker(mainThread));
LockSupport.unpark(mainThread);
System.out.println("after unpark, " + LockSupport.getBlocker(mainThread));
});
thread.start();
TimeUnit.SECONDS.sleep(1);
System.out.println("before park");
// 等待獲取許可
LockSupport.park("Park");
System.out.println("after park");
}
(2) park與interrupt
public void test3() throws Exception {
Thread thread = new Thread(() -> {
System.out.println(Thread.currentThread().isInterrupted()); // false
LockSupport.park();
System.out.println(Thread.currentThread().isInterrupted()); // true
});
thread.start();
TimeUnit.SECONDS.sleep(1);
thread.interrupt();
System.in.read();
}
簡而言之:
- 實現機制和 wait/notify 有所不同,面向的是執行緒
- 不需要依賴監視器
- 與 wait/notify 沒有交集
- 使用起來方便靈活
參考:
- 《LockSupport解析與使用》:https://blog.csdn.net/secsf/article/details/78560013
每天用心記錄一點點。內容也許不重要,但習慣很重要!