并发包中的LockSupport工具类

2021-09-05  本文已影响0人  nieniemin

一、 LockSupport简介

LockSupport类是一个Java6(JSR166-JUC)引入的一个工具类,它的主要作用是对线程进行挂起和唤醒,它是创建锁和其他同步类的基础。

LockSupport类的核心方法其实就两个:park()和unpark(),其中park()方法用来阻塞当前调用线程,unpark()方法用于唤醒指定线程。这和Object的wait/notify、Condition的await/signal、以及Semaphore的acquire/release功能类似。
但是LockSupport的这两种方法从语意上讲比Object类的方法更清晰,而且可以针对指定线程进行阻塞和唤醒
注意:park方法真正的实现是Unsafe类

private static final sun.misc.Unsafe UNSAFE;
public static void park() {
        UNSAFE.park(false, 0L);
}

LockSupport类使用了一种名为Permit(许可)的概念来做到阻塞和唤醒线程的功能,可以把许可看成是一种(0,1)信号量(Semaphore),但与 Semaphore 不同的是,许可的累加上限是1。
初始时,permit为0,当调用unpark()方法时,线程的permit加1,当调用park()方法时,如果permit为0,则调用线程进入阻塞状态。

二、 LockSupport API

Park方法:

如果调用LockSupport.park()方法的线程已经拿到了与LockSupport关联的许可证,则调用时会马上返回,否则调用线程会被禁止参与线程的调度,也就是会被阻塞挂起。

public class LockSupportMain {
    public static void main(String[] args) {
        System.out.println("main线程----------park前");
   //直接在main函数中调用park()方法,当前线程被挂起。
        //在默认情况下,调用线程是不持有许可证的。
        LockSupport.park();
        System.out.println("main线程----------park后");
    }
}
****************************只会输出调用park()方法前内容*******
main线程----------park前

unPark(Thread thread):

当一个线程调用LockSupport.unpark()方法时,如果参数thread线程没有持有thread与LockSupport类关联的许可证,则让thread线程持有;

而如果thread之前因调用LockSupport.park()方法时被挂起,则调用LockSupport.unpark()方法后,该线程会被唤醒。

而如果thread之前没有调用LockSupport.park()方法,则调用LockSupport.unpark()方法后,再调用LockSupport.park()方法,其会立刻返回。

public class LockSupportMain {
    public static void main(String[] args) {
        System.out.println("main线程----------park前");
        //使用当前线程获取到许可证
        LockSupport.unpark(Thread.currentThread());
        LockSupport.park();
        System.out.println("main线程----------park后");
    }
}
*******************************************
main线程----------park前
main线程----------park后
public class LockSupportMain {
    public static void main(String[] args) {
        Thread thread = new Thread(() -> {
            System.out.println("子线程开始...");
            //调用LockSupport.park()方法,挂起自己
            //默认情况下,子线程没有持有许可证,因而它会把自己挂起。
            LockSupport.park();
            System.out.println("调用park后,改行不会打印,直到LockSupport.unpark(thread)唤醒后,
才会打印这行,子线程才会结束.");

        });
        thread.start();

        try {
            Thread.sleep(10_000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        //10s后,main线程调用LockSupport.unpark()方法让thread线程持有许可证,
        //然后LockSupport.park()方法返回。
        LockSupport.unpark(thread);
    }
}

LockSupport的使用过程中还需要注意以下几点:

上一篇 下一篇

猜你喜欢

热点阅读