简述LockSupports

71 阅读3分钟

“开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 1 天,点击查看活动详情

LockSupport是JDK中比较底层的类,用来创建锁和其他同步工具类的基本线程阻塞原语。

Java锁和同步器框架的核心 AQS: AbstractQueuedSynchronizer,就是通过调用 LockSupport .park()和 LockSupport .unpark()实现线程的阻塞和解除阻塞的。

小试一个Demo

交替打印

public class Solution {
    static Thread t1;
    static Thread t2;

    public static void main(String[] args) {
       t1 = new Thread(() -> {
           for(int i = 0;i <= 10;i++){
               if((i & 1) == 0){
                   System.out.println("t1 : " + i);
                   LockSupport.unpark(t2);
                   LockSupport.park();
               }
           }
        });
        t2 = new Thread(() -> {
            for(int i = 0;i <= 10;i++){
                if((i & 1) != 0){
                    LockSupport.park();
                    System.out.println("t2 : " + i);
                    LockSupport.unpark(t1);
                }
            }
        });
        t1.start();
        t2.start();
    }
}

Thread.sleep()和Object.wait()的区别

  1. Thread.sleep()不会释放占有的锁,Object.wait()会释放占有的锁;
  2. Thread.sleep()必须传入时间,Object.wait()可传可不传,不传表示一直阻塞下去;
  3. Thread.sleep()到时间了会自动唤醒,然后继续执行;Object.wait()不带时间的,需要另一个线程使用Object.notify()唤醒;
  4. Object.wait()带时间的,假如没有被notify,到时间了会自动唤醒,这时又分好两种情况,一是立即获取到了锁,线程自然会继续执行;二是没有立即获取锁,线程进入同步队列等待获取锁;

Thread.sleep()和LockSupport.park()的区别

  1. 都是阻塞当前线程的执行,且都不会释放当前线程占有的资源
  2. Thread.sleep()没办法从外部唤醒,只能自己醒来
  3. LockSupport.park()方法可以被另一个线程调用LockSupport.unpark()方法唤醒;
  4. Thread.sleep()方法声明上抛出了InterruptedException中断异常,所以调用者需要捕获这个异常或者再抛出;
  5. LockSupport.park()方法不需要捕获中断异常;

Object.wait()和LockSupport.park()的区别

二者都会阻塞当前线程的运行,他们有什么区别呢?经过上面的分析相信你一定很清楚了,真的吗?往下看!

(1)Object.wait()方法需要在synchronized块中执行;

(2)LockSupport.park()可以在任意地方执行;

(3)Object.wait()方法声明抛出了中断异常,调用者需要捕获或者再抛出;

(4)LockSupport.park()不需要捕获中断异常

(5)Object.wait()不带超时的,需要另一个线程执行notify()来唤醒,但不一定继续执行后续内容;

(6)LockSupport.park()不带超时的,需要另一个线程执行unpark()来唤醒,一定会继续执行后续内容;

(7)如果在wait()之前执行了notify()会怎样?抛出IllegalMonitorStateException异常

(8)如果在park()之前执行了unpark()会怎样?线程不会被阻塞,直接跳过park(),继续执行后续内容;


LockSupport.park()会释放锁资源吗

不会,它只负责阻塞当前线程,释放锁资源实际上是在Condition的await()方法中实现的。

park函数是将当前Thread阻塞,而unpark函数则是将指定线程Thread唤醒

关于许可

  • park和unpark最核心的地方在于许可,unpark为指定线程提供许可,park是等待一个许可,否则阻塞在parl操作上
  • unpark可以在park之前,先提供许可再消费许可,比如生产消费者模型,可能消费者还没开始消费,生产者就已经生产好了