当前位置: 代码迷 >> 综合 >> LockSupport 深入源码解析
  详细解决方案

LockSupport 深入源码解析

热度:41   发布时间:2024-01-17 01:25:02.0

??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版本,不同版本间可能存在差异。

??如果有哪里有不明白或不清楚的内容,欢迎留言哦!