LockSupport 深入源码解析

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

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

猜你喜欢

转载自blog.csdn.net/securitit/article/details/106984563