news 2026/4/24 20:43:45

JUC并发编程:LockSupport.park() 与 unpark() 深度解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
JUC并发编程:LockSupport.park() 与 unpark() 深度解析

一、前言

在Java并发编程中,AQS (AbstractQueuedSynchronizer) 是实现锁(如 ReentrantLock)、同步器(如 CountDownLatch)的核心基础。而 AQS 能够实现线程的阻塞与唤醒,其底层完全依赖于LockSupport工具类。

LockSupport 是 JUC 包中的一个工具类,主要用于挂起(block)和唤醒(wake up)线程。它所有的方法都是静态的,底层通过Unsafe类实现。


二、基本使用

LockSupport 主要是通过 park() 和 unpark(Thread thread) 来实现的。

  • park(): 阻塞当前线程,直到获得“许可”或被中断。

  • unpark(Thread thread): 给指定线程发放一个“许可”,如果该线程被阻塞,则将其唤醒。

1. 标准用法:先 park 后 unpark

这是最直观的用法,主线程让子线程阻塞,然后三秒后唤醒它。

import java.util.concurrent.locks.LockSupport; public class ParkUnparkDemo { public static void main(String[] args) throws InterruptedException { Thread t1 = new Thread(() -> { System.out.println(Thread.currentThread().getName() + " --- 1. 开始运行"); // 阻塞当前线程 LockSupport.park(); System.out.println(Thread.currentThread().getName() + " --- 3. 被唤醒"); }, "t1"); t1.start(); // 睡眠3秒,确保t1先执行并进入park状态 Thread.sleep(3000); System.out.println(Thread.currentThread().getName() + " --- 2. 发起唤醒"); // 唤醒线程t1 LockSupport.unpark(t1); } }

运行结果:

codeText

t1 --- 1. 开始运行 main --- 2. 发起唤醒 t1 --- 3. 被唤醒

2. 特殊用法:先 unpark 后 park

这是 LockSupport 与 Object.wait() 最大的区别之一。
即使 unpark 操作发生在 park 之前,线程依然可以正常通过(不会永久阻塞)。

import java.util.concurrent.locks.LockSupport; public class UnparkFirstDemo { public static void main(String[] args) throws InterruptedException { Thread t1 = new Thread(() -> { try { // 让子线程睡一会儿,保证主线程先执行 unpark Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + " --- 2. 准备park"); // 因为之前已经有许可了,这里不会阻塞,直接通过 LockSupport.park(); System.out.println(Thread.currentThread().getName() + " --- 3. park结束,继续执行"); }, "t1"); t1.start(); System.out.println(Thread.currentThread().getName() + " --- 1. 提前发放许可"); // 提前给t1线程发放许可 LockSupport.unpark(t1); } }

原理简述:unpark 就像是给线程的钱包里预存了一张票,等线程执行 park 需要买票进站时,发现钱包里已经有票了,直接刷票进站,无需等待。


三、与 Object.wait/notify 的区别(重点)

在面试和实际开发中,这两组机制经常被拿来对比:

特性Object.wait() / notify()LockSupport.park() / unpark()
所属对象Object 类的方法LockSupport 类的静态方法
锁的要求必须在 synchronized 代码块中执行,否则抛 IllegalMonitorStateException不需要获取任何锁,随时随地可调用
锁的释放执行 wait 会释放当前持有的锁执行 park不会释放当前持有的锁(容易死锁,需注意)
执行顺序必须先 wait 后 notify。如果先 notify 后 wait,线程会永久等待顺序无关。可以先 unpark 存入许可,后 park 消费许可
中断响应抛出 InterruptedException 异常不抛异常,park 方法直接返回,需要通过 Thread.interrupted() 检查状态

四、底层原理深度解析

LockSupport 的底层是一个 native 方法,最终调用的是 JVM 内部(C++实现)的 Parker 对象。核心理念是"Permit"(许可)

1. Permit (许可) 机制

我们可以将 Permit 理解为一个二元信号量(0 或 1),它不累加

  • park() 流程:

    1. 检查当前线程是否有许可(Permit)。

    2. 如果有(Permit = 1):消耗许可(Permit 变为 0),park 方法立即返回,线程继续运行。

    3. 如果没有(Permit = 0):阻塞当前线程,直到被唤醒。

  • unpark(Thread t) 流程:

    1. 将指定线程的许可设置为 1(Permit 变为 1)。

    2. 注意:因为是二元信号量,多次调用 unpark 不会叠加。unpark 100次,Permit 依然是 1。此时调用一次 park 就会消耗掉这个许可,第二次调用 park 依然会阻塞。

2. 源码级验证 (HotSpot VM)

在 JVM 源码(os_linux.cpp 和 os_windows.cpp 等)中,每个 Java 线程都有一个对应的 C++ 类 Parker 实例。

Parker 类主要包含三个核心变量:

  1. _counter: 记录许可数量(0 或 1)。

  2. _mutex: 互斥锁(用于保护操作)。

  3. _cond: 条件变量(用于线程挂起)。

Java底层图示:

C++ 伪代码逻辑演示

park() 的大致逻辑:

void Parker::park(bool isAbsolute, jlong time) { // 1. 如果已有许可(_counter > 0),直接消耗许可并返回 if (_counter > 0) { _counter = 0; return; } // 2. 获取互斥锁 pthread_mutex_lock(_mutex); // 3. 再次检查许可(防止并发情况) if (_counter > 0) { _counter = 0; pthread_mutex_unlock(_mutex); return; } // 4. 真正阻塞,等待信号(类似Java的wait) // 这里会释放锁并等待,直到被unpark唤醒或中断 pthread_cond_wait(_cond, _mutex); // 5. 唤醒后,将许可归零 _counter = 0; pthread_mutex_unlock(_mutex); }

unpark() 的大致逻辑:

void Parker::unpark(Thread* thread) { // 1. 获取互斥锁 pthread_mutex_lock(_mutex); // 2. 只有当许可为0时,才设置为1(不可累加) // 但无论之前是多少,最终状态都是1 int s = _counter; _counter = 1; // 3. 如果线程之前是阻塞状态(s < 1),唤醒它 if (s < 1) { // 发送信号唤醒在 _cond 上等待的线程 pthread_cond_signal(_cond); } pthread_mutex_unlock(_mutex); }

五、常见面试题与坑

1. 为什么推荐使用 park(Object blocker)?

在 Java 6 之后,LockSupport 新增了 park(Object blocker) 方法。

  • blocker 是用来标识当前线程在等待什么对象(通常传入 this)。

  • 作用:当使用 jstack 或 Profiler 工具排查死锁或性能问题时,能够显示出线程是被哪个对象 block 住的,极大地方便了问题定位。

对比:

  • park() 在 dump 文件中显示:parking to wait for <0x0000000000000000> (无信息)

  • park(this) 在 dump 文件中显示:parking to wait for <0x000000076b3820f0> (a java.util.concurrent.locks.ReentrantLock$NonfairSync)

2. 中断(Interrupt)能唤醒 park 吗?

能。
当一个线程被 park 阻塞时,如果其他线程调用了该线程的 interrupt() 方法,park 会立即返回。
注意:不会抛出 InterruptedException,你需要手动检查中断标志位。

Thread t1 = new Thread(() -> { LockSupport.park(); // 这里的代码会在 unpark 或 interrupt 后执行 if (Thread.currentThread().isInterrupted()) { System.out.println("被中断唤醒了"); } }); t1.start(); t1.interrupt(); // 线程会立刻从 park 中醒来

3. 多次 unpark,能否抵消多次 park?

不能。

LockSupport.unpark(Thread.currentThread()); LockSupport.unpark(Thread.currentThread()); // 此时 permit 还是 1 LockSupport.park(); // 消耗 permit (1 -> 0),通过 LockSupport.park(); // permit 为 0,阻塞!

六、总结

  1. LockSupport 是 JUC 并发包的基石,AQS 依靠它来挂起和唤醒线程。

  2. 它利用Permit(许可)机制,解耦了阻塞和唤醒的顺序限制(可以先唤醒后阻塞)。

  3. 它底层利用操作系统的 Mutex 和 Condition Variable 实现,轻量且高效。

  4. 在使用时,要注意它不释放锁的特性,避免造成死锁。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/23 12:25:32

互联网大厂Java求职面试:从Spring Boot到微服务架构实践

场景&#xff1a;互联网大厂Java小白求职者面试 面试背景 一位初入职场的小白程序员“超好吃”刚刚投递了某互联网大厂的Java开发岗位&#xff0c;今天是他的技术面试环节。面试官是一位严肃但不失风趣的资深工程师&#xff0c;场景设定为电商平台的技术开发。第一轮提问&#…

作者头像 李华
网站建设 2026/4/23 12:11:11

13.2 基于基础模型的机器人控制:探索感知、规划与执行的智能融合

13.2 基于基础模型的机器人控制:探索感知、规划与执行的智能融合 13.2.1 引言:基础模型带来的范式扩展 长期以来,机器人控制系统的设计遵循着模块化范式:感知模块(如目标检测、位姿估计)将原始传感器数据转化为结构化信息;规划模块(如路径规划、任务规划)根据信息和…

作者头像 李华
网站建设 2026/4/22 17:23:41

眼调节训练灯:防控近视的“黑科技”,究竟如何守护孩子的视界?

在电子设备普及、近距离用眼成为常态的当下&#xff0c;儿童青少年近视率居高不下&#xff0c;已成为影响孩子身心健康的重要问题。家长们尝试过增加户外活动、控制用眼时长、改善读写姿势等多种方法&#xff0c;但近视防控的效果仍不尽如人意。究其原因&#xff0c;很多防控手…

作者头像 李华
网站建设 2026/4/23 12:29:04

全网最全继续教育TOP10AI论文软件测评与推荐

全网最全继续教育TOP10AI论文软件测评与推荐 2026年继续教育AI论文工具测评&#xff1a;为何需要一份权威榜单&#xff1f; 随着人工智能技术的不断进步&#xff0c;AI写作工具在学术研究和继续教育领域的应用日益广泛。然而&#xff0c;面对市场上众多产品&#xff0c;如何选择…

作者头像 李华
网站建设 2026/4/23 12:31:53

基于Java的家教智慧管理系统的设计与实现全方位解析:附毕设论文+源代码

1. 为什么这个毕设项目值得你 pick ? 家教智慧管理系统整合学校、年级、科目等多维度信息&#xff0c;实现数据的高效管理与智能匹配。系统功能模块化设计确保普通员工和部门领导操作简便&#xff0c;提高工作效率的同时降低开发难度。相比传统选题&#xff0c;该系统更加贴近…

作者头像 李华
网站建设 2026/4/23 17:23:44

提示工程与社会变革:提示工程架构师引领社会变革新潮流

提示工程与社会变革&#xff1a;提示工程架构师引领社会变革新潮流 引言&#xff1a;从“问问题”到“定义未来” 清晨&#xff0c;一位医生打开电子病历系统&#xff0c;输入一段提示&#xff1a;“请分析患者近3个月的血糖数据&#xff0c;标注异常波动点&#xff0c;并推荐个…

作者头像 李华