LockSupport的用法及原理

是什么

LockSupport是一個線程阻塞工具類,所有的方法都是靜態(tài)方法,可以讓線程在任意位置阻塞,當(dāng)然阻塞之后肯定得有喚醒的方法。

有什么用

接下面我來看看LockSupport有哪些常用的方法。主要有兩類方法:parkunpark。

public static void park(Object blocker); // 暫停當(dāng)前線程
public static void parkNanos(Object blocker, long nanos); // 暫停當(dāng)前線程,不過有超時時間的限制
public static void parkUntil(Object blocker, long deadline); // 暫停當(dāng)前線程,直到某個時間
public static void park(); // 無期限暫停當(dāng)前線程
public static void parkNanos(long nanos); // 暫停當(dāng)前線程,不過有超時時間的限制
public static void parkUntil(long deadline); // 暫停當(dāng)前線程,直到某個時間
public static void unpark(Thread thread); // 恢復(fù)當(dāng)前線程
public static Object getBlocker(Thread t);

為什么叫park呢,park英文意思為停車。我們?nèi)绻裈hread看成一輛車的話,park就是讓車停下,unpark就是讓車啟動然后跑起來。

我們寫一個例子來看看這個工具類怎么用的。

public class LockSupportDemo {

    public static Object u = new Object();
    static ChangeObjectThread t1 = new ChangeObjectThread("t1");
    static ChangeObjectThread t2 = new ChangeObjectThread("t2");

    public static class ChangeObjectThread extends Thread {
        public ChangeObjectThread(String name) {
            super(name);
        }
        @Override public void run() {
            synchronized (u) {
                System.out.println("in " + getName());
                LockSupport.park();
                if (Thread.currentThread().isInterrupted()) {
                    System.out.println("被中斷了");
                }
                System.out.println("繼續(xù)執(zhí)行");
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        t1.start();
        Thread.sleep(1000L);
        t2.start();
        Thread.sleep(3000L);
        t1.interrupt();
        LockSupport.unpark(t2);
        t1.join();
        t2.join();
    }
}

運(yùn)行的結(jié)果如下:

in t1
被中斷了
繼續(xù)執(zhí)行
in t2
繼續(xù)執(zhí)行

這兒parkunpark其實(shí)實(shí)現(xiàn)了waitnotify的功能,不過還是有一些差別的。

  1. park不需要獲取某個對象的鎖
  2. 因?yàn)橹袛嗟臅r候park不會拋出InterruptedException異常,所以需要在park之后自行判斷中斷狀態(tài),然后做額外的處理

我們再來看看Object blocker,這是個什么東西呢?這其實(shí)就是方便在線程dump的時候看到具體的阻塞對象的信息。

"t1" #10 prio=5 os_prio=31 tid=0x00007f95030cc800 nid=0x4e03 waiting on condition [0x00007000011c9000]
   java.lang.Thread.State: WAITING (parking)
    at sun.misc.Unsafe.park(Native Method)
    at java.util.concurrent.locks.LockSupport.park(LockSupport.java:304)
    // `下面的這個信息`
    at com.wtuoblist.beyond.concurrent.demo.chapter3.LockSupportDemo$ChangeObjectThread.run(LockSupportDemo.java:23) // 
    - locked <0x0000000795830950> (a java.lang.Object)

還有一個地方需要注意,相對于線程的stop和resume,park和unpark的先后順序并不是那么嚴(yán)格。stop和resume如果順序反了,會出現(xiàn)死鎖現(xiàn)象。而park和unpark卻不會。這又是為什么呢?還是看一個例子

public class LockSupportDemo {

    public static Object u = new Object();
    static ChangeObjectThread t1 = new ChangeObjectThread("t1");

    public static class ChangeObjectThread extends Thread {

        public ChangeObjectThread(String name) {
            super(name);
        }

        @Override public void run() {
            synchronized (u) {
                System.out.println("in " + getName());
                try {
                    Thread.sleep(1000L);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                LockSupport.park();
                if (Thread.currentThread().isInterrupted()) {
                    System.out.println("被中斷了");
                }
                System.out.println("繼續(xù)執(zhí)行");
            }
        }
    }

    public static void main(String[] args) {
        t1.start();
        LockSupport.unpark(t1);
        System.out.println("unpark invoked");
    }
}

t1內(nèi)部有休眠1s的操作,所以unpark肯定先于park的調(diào)用,但是t1最終仍然可以完結(jié)。這是因?yàn)?code>park和unpark會對每個線程維持一個許可(boolean值)

  1. unpark調(diào)用時,如果當(dāng)前線程還未進(jìn)入park,則許可為true
  2. park調(diào)用時,判斷許可是否為true,如果是true,則繼續(xù)往下執(zhí)行;如果是false,則等待,直到許可為true

我們再看看jdk的文檔描述

park描述
unpark描述

總結(jié)一下

  1. park和unpark可以實(shí)現(xiàn)類似wait和notify的功能,但是并不和wait和notify交叉,也就是說unpark不會對wait起作用,notify也不會對park起作用。
  2. park和unpark的使用不會出現(xiàn)死鎖的情況
  3. blocker的作用是在dump線程的時候看到阻塞對象的信息
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容