LockSupport简述

94 阅读1分钟

一、概念

LockSupport是用来创建锁和其他同步类的基本线程阻塞原语。

LockSupport是一个线程阻塞工具类,所有的方法都是静态方法,可以让线程在任意位置阻塞,阻塞之后也有对应的唤醒方法。归根结底,LockSupport调用的是sun.misc.Unsafe中的native代码。

LockSupport提供park()和unpark()方法实现阻塞线程和解除线程阻塞的过程。

LockSupport类使用了一种名为Permit(许可)的概念来做到阻塞和唤醒线程的功能。每个线程都有一个许可(permit),permit只有两个值,1和0,默认是0。可以把许可看做是一种(0,1)信号量,但是与Semaphore不同的是,许可的累加上限是1。

  • park()表示消耗一个许可,调用park()时,如果许可可用则park()返回,线程不会阻塞;如果没有许可则一直阻塞到许可可用。
  • unpark()表示增加一个许可,多次调用并不会积累许可,因为许可数最大值为1

调用一次unpark()就加1变成1,调用一次park()就会消费permit,也就是将1变成0,同时park立即返回。如再次调用park(),会变成阻塞(因为permit为0了,会阻塞在这里,一直到permit变成1),这时调用unpark()会把permit置为1。

二、代码演示

public class LockDemo {

    public static void main(String[] args) {
        Thread a = new Thread(() -> {
            System.out.println(Thread.currentThread().getName() + "come in");
            //当前线程a被阻塞,等待通知等待放行,它要通过需要许可证
            LockSupport.park();
            System.out.println(Thread.currentThread().getName() + "被唤醒");
        }, "a");
        a.start();

        //暂停几秒钟线程
        try {
            TimeUnit.SECONDS.sleep(3L);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

        new Thread(() -> {
            System.out.println(Thread.currentThread().getName() + "come in");
            //唤醒线程a
            LockSupport.unpark(a);
            System.out.println(Thread.currentThread().getName() + "被唤醒");
        }, "b").start();
    }
}