LockSupport

1.概念

LockSupport是用来进行线程的通信的,是一个线程阻塞的工具类,其中里面的方法都是静态方法,park()和unpark()的作用分别是阻塞线程和唤醒线程。

2.线程等待和唤醒机制

  • 方式一:使用Object中的wait()方法让线程等待,使用Object中的notify()方法唤醒线程

  • 方式二:使用JUC包中的Condition的await()方法让线程等待,使用signal()方法唤醒线程

  • 方式三:LockSupport类可以阻塞当前线程以及唤醒指定被阻塞的线程

方式一必须在同步代码块或者同步方法中成对使用,先wait后notify才能正常使用。

方式二必须先获取锁后才能使用,并且是先await后signal才能正常使用。

3.LockSupport的强大之处

LockSupport类中使用了一种名为Permit(许可证)的概念来实现阻塞和唤醒线程的功能,而且许可证只能有一个,不能累加

park:许可证默认没有所以会阻塞,等到发放许可才能唤醒。

unpark:发放许可证,自动唤醒等待的线程。

public class LockSupportDemo {

    public static void main(String[] args) {
        Thread t1 = new Thread(() -> {
            System.out.println(Thread.currentThread().getName() + "\t -----------come in");
            LockSupport.park(); //阻塞
            System.out.println(Thread.currentThread().getName() + "\t ----------被唤醒");
        }, "t1");
        t1.start();

        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        new Thread(() -> {
            LockSupport.unpark(t1);//发放许可
            System.out.println(Thread.currentThread().getName() + "\t ----------发出通知");
        }, "t2").start();

    }
}

形象的理解:线程阻塞时需要消耗凭证,这个凭证最多只有一个,当调用park时,如果有许可,那么就直接消耗,继续向下进行,如果没有,则阻塞等待许可证的发放。当调用unpark时,发放一个许可证,多次调用不会累加。

4.面试高频题

4.1为什么LockSupport可以突破wait/notify的原有调用顺序?

因为unpark获得了一个凭证,之后再调用park方法,就可以名正言顺的凭证消费,故不会阻塞,先发放了凭证后续可以畅通无阻。

4.2为什么连续调用两次unpark方法,再调用两次park方法,还是会阻塞?

因为凭证的数量最大为1,而调用两次park方法却需要两个许可,证不够,所以会阻塞。

 

你可能感兴趣的:(并发编程,java,jvm,开发语言)