Skip to content

AQS LockSupport源码分析

一、LockSupport概述

LockSupport是Java并发包中用于构建锁和其他同步组件的基础工具类,通过park()unpark()方法实现线程的阻塞与唤醒。它类似于信号量机制,但其"许可证"最多只有一个。

二、核心方法解析

1. park() 方法

java
public static void park() {
  UNSAFE.park(false, 0L);
}
  • 功能:阻塞当前线程,直到其他线程调用unpark()或线程被中断。
  • 许可证机制:如果线程已有许可证(即之前调用过unpark()),则立即返回并消费该许可证;否则线程进入阻塞状态。
  • 中断处理:若线程在阻塞期间被中断,会立即返回且不抛出异常,需通过Thread.interrupted()检测中断状态。

2. unpark(Thread thread) 方法

java
public static void unpark(Thread thread) {
    if (thread != null)
      UNSAFE.unpark(thread);
}
  • 功能:为指定线程发放许可证,使其从park()中返回。
  • 特点
    • 可以先于park()调用,确保线程不会阻塞。
    • 多次调用unpark()仅发放一个许可证。

三、底层原理简析

每个线程内部维护一个Parker对象,包含三个关键部分:

  • _counter:表示是否可以调用park()的许可证计数(最大为1)。
  • _cond:条件变量,用于线程阻塞等待。
  • _mutex:互斥锁,保证线程安全地访问_counter

1. park() 的执行流程

  1. 检查_counter值:
    • 若为1,则直接消费许可证并继续执行,无需阻塞。
    • 若为0,则获取_mutex锁,并将线程加入_cond条件队列等待。
  2. 线程进入阻塞状态,等待unpark()唤醒。

2. unpark(Thread thread) 的执行流程

  1. 设置目标线程的_counter为1。
  2. 若目标线程已处于阻塞状态,则唤醒它。
  3. 目标线程恢复后,检查_counter并消费许可证。

四、使用示例

以下是一个基于LockSupport实现的简单FIFO互斥锁示例:

java
class FIFOMutex {
    private final AtomicBoolean locked = new AtomicBoolean(false);
    private final Queue<Thread> waiters = new ConcurrentLinkedQueue<>();

    public void lock() {
        boolean wasInterrupted = false;
        waiters.add(Thread.currentThread());
        while (waiters.peek() != Thread.currentThread() || !locked.compareAndSet(false, true)) {
            LockSupport.park(this);
            if (Thread.interrupted())
                wasInterrupted = true;
        }
        waiters.remove();
        if (wasInterrupted)
            Thread.currentThread().interrupt();
    }

    public void unlock() {
        locked.set(false);
        LockSupport.unpark(waiters.peek());
    }
}
  • 说明
    • lock()方法中,线程必须是队首元素才能尝试获取锁。
    • 若锁已被占用,则线程调用park()进入阻塞状态。
    • unlock()方法释放锁后,唤醒队首线程继续竞争锁。

五、总结

  • 优势
    • 支持精确唤醒特定线程。
    • 不依赖对象监视器(monitor),使用更灵活。
    • 允许先调用unpark()再调用park()
  • 应用场景
    • 构建高级同步工具(如AQS框架中的各类锁)。
    • 需要精确控制线程阻塞与唤醒的场景。

通过上述分析可见,LockSupport是Java并发编程中非常强大的基础工具,尤其在AQS框架中扮演着重要角色。