LockSupport是一个线程工具类,所有的方法都是静态方法,可以在线程任意位置阻塞、唤醒线程。LockSupport的功能是依赖Unsafe类实现的。
演示示例:
package com.securitit.serialize.locks;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.LockSupport;
public class LockSupportTester {
public static void main(String[] args) throws Exception {
final Thread mainThread = Thread.currentThread();
new Thread(() -> {
try {
TimeUnit.SECONDS.sleep(3);
System.out.println("唤醒线程:" + mainThread.getName());
LockSupport.unpark(mainThread);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}).start();
System.out.println("阻塞线程:" + mainThread.getName());
LockSupport.park();
}
}
输出结果:
阻塞线程:main
唤醒线程:main
从输出结果可以看出,主线程通过LockSupport.park()进行线程阻塞,新建线程通过mainThread唤醒主线程。
源码分析:
package java.util.concurrent.locks;
import sun.misc.Unsafe;
public class LockSupport {
// Construct.禁止实例化.
private LockSupport() {}
// 记录线程是被blocker阻塞.
private static void setBlocker(Thread t, Object blocker) {
// Even though volatile, hotspot doesn't need a write barrier here.
UNSAFE.putObject(t, parkBlockerOffset, arg);
}
// 唤醒线程.
public static void unpark(Thread thread) {
if (thread != null)
UNSAFE.unpark(thread);
}
// 阻塞线程.
public static void park(Object blocker) {
// 获取当前线程.
Thread t = Thread.currentThread();
// 记录线程被blocker阻塞.
setBlocker(t, blocker);
// 调用Unsafe.park方法阻塞线程.
UNSAFE.park(false, 0L);
// 清除线程被blocker阻塞的信息.
setBlocker(t, null);
}
// 指定超时时间阻塞线程.
public static void parkNanos(Object blocker, long nanos) {
if (nanos > 0) {
// 获取当前线程.
Thread t = Thread.currentThread();
// 记录线程被blocker阻塞.
setBlocker(t, blocker);
// 调用Unsafe.park方法阻塞线程.
UNSAFE.park(false, nanos);
// 清除线程被blocker阻塞的信息.
setBlocker(t, null);
}
}
// 指定阻塞线程至某个时间点.
public static void parkUntil(Object blocker, long deadline) {
// 获取当前线程.
Thread t = Thread.currentThread();
// 记录线程被blocker阻塞.
setBlocker(t, blocker);
// 调用Unsafe.park方法阻塞线程.
UNSAFE.park(true, deadline);
// 清除线程被blocker阻塞的信息
setBlocker(t, null);
}
// 获取线程阻塞者.
public static Object getBlocker(Thread t) {
if (t == null)
throw new NullPointerException();
return UNSAFE.getObjectVolatile(t, parkBlockerOffset);
}
// 阻塞线程.
public static void park() {
UNSAFE.park(false, 0L);
}
// 指定超时时间阻塞线程.
public static void parkNanos(long nanos) {
if (nanos > 0)
UNSAFE.park(false, nanos);
}
// 指定阻塞线程到时间点.
public static void parkUntil(long deadline) {
UNSAFE.park(true, deadline);
}
}
LockSupport源码实现相对比较简单,底层都是通过Unsafe的native方法由操作系统直接进行,可以提供更高的效率。
LockSupport的park/unpark与Object的wait/notify区别:
· wait/notify是Object的方法,在调用这两个方法前必须先获得锁,但是park不需要获取某个对象的锁就可以阻塞线程。
· notify只能随机选择一个唤醒,无法唤醒指定线程,unpark可以唤醒一个指定的线程。
注:文中源码均来自于JDK1.8版本,不同版本间可能存在差异。
如果有哪里有不明白或不清楚的内容,欢迎留言哦!