一、概念
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();
}
}