概述
1、LockSupport是Java6引入的一个工具类, 用于挂起和唤醒线程;
2、所有的方法都是静态方法,可以让线程在任意位置阻塞,当然阻塞之后肯定得有唤醒的方法。
3、通过提供park() 和 unpark() 方法实现阻塞线程和解除线程阻塞, 实现阻塞与解除阻塞是基于许可(permit), permit相当于一个信号量,只能取0和1, 默认为0;
源码分析
构造方法:
只有一个无参构造方法,无需解析。
重要属性:
private static final sun.misc.Unsafe UNSAFE;
private static final long parkBlockerOffset;
private static final long SEED;
private static final long PROBE;
private static final long SECONDARY;
主要是UNSAFE和parkBlockerOffset:
UNSAFE: Unsafe对象, 提供CAS操作, 获取对象内存中字段的偏移量, 设置对象偏移量对应的字段的值;
parkBlockerOffset 存储Thread类对象中parkBlocker字段的偏移量;
常用方法:
// UNSAFE.park第一个参数var1表示是否为相对时间, 第二个参数var2为超时等待时间
// var1为fasle时, var2的单位为纳秒, var2为0时, 会一直等待, 直到被unpark()唤醒或者被中断后才会向下执行;
// var2为true时, 表示绝对时间, var2单位为毫秒
public static void park() {
UNSAFE.park(false, 0L);
}
// 唤醒thread线程, 对一个thread调用一次和多次效果一样;
public static void unpark(Thread thread) {
if (thread != null)
UNSAFE.unpark(thread);
}
可以看出,LockSupport 是基于 sun.misc.Unsafe 实现的。
LockSupport的设计思路就是为每一个线程设置一个许可(permit),其实就是一个值。这个permit就相当于一个开关,0代表关闭,1代表打开。默认是0的状态。调用一次unpark就加1变成1,调用一次park会消费permit, 也就是将1变成0,同时park立即返回。再次调用park会变成block(因为permit为0了,会阻塞在这里,直到permit变为1), 这时调用unpark会把permit置为1。每个线程都有一个相关的permit, permit最多只有一个,重复调用unpark也不会积累,也就是说你可以重复调用多次unpark方法这个值也一直是1,而不会因为多次调用而累加,调用一次park后这个值就会变成0,线程就会被阻塞。你也可以先调用unpark方法,将值先设置为1,然后再调用park方法,调用park方法时这个permit已经时1了那么就会立即返回,不会阻塞线程,并且将permit设置为0.这就是开篇说到的与Thread.suspend()和resume()由于先后顺序而产生的死锁的区别。