“开启掘金成长之旅!这是我参与「掘金日新计划 · 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()的区别
- Thread.sleep()不会释放占有的锁,Object.wait()会释放占有的锁;
- Thread.sleep()必须传入时间,Object.wait()可传可不传,不传表示一直阻塞下去;
- Thread.sleep()到时间了会自动唤醒,然后继续执行;Object.wait()不带时间的,需要另一个线程使用Object.notify()唤醒;
- Object.wait()带时间的,假如没有被notify,到时间了会自动唤醒,这时又分好两种情况,一是立即获取到了锁,线程自然会继续执行;二是没有立即获取锁,线程进入同步队列等待获取锁;
Thread.sleep()和LockSupport.park()的区别
- 都是阻塞当前线程的执行,且都不会释放当前线程占有的资源
- Thread.sleep()没办法从外部唤醒,只能自己醒来
- LockSupport.park()方法可以被另一个线程调用LockSupport.unpark()方法唤醒;
- Thread.sleep()方法声明上抛出了InterruptedException中断异常,所以调用者需要捕获这个异常或者再抛出;
- 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之前,先提供许可再消费许可,比如生产消费者模型,可能消费者还没开始消费,生产者就已经生产好了