大家好,我是小米,一个在Java世界里摸爬滚打多年的大哥哥。今天给大家分享一个社招面试中常见但又容易忽略的知识点——LockSupport。
这个故事,要从我前几天面试的一道面试题说起。
一次社招面试中的LockSupport拷问事情是这样的,我面试了一家互联网大厂,面试官上来就是几个Java基础问题,接着就开始深入多线程。
面试官:“你了解 LockSupport 吗?请你讲讲它的原理和应用场景。”
我(内心慌张但表面镇定):“LockSupport 是一个用于线程阻塞和唤醒的工具类,本质上是基于 Unsafe 类的 park 和 unpark 方法实现的。”
面试官(微微一笑):“那你能说说它和 Object.wait/notify、ReentrantLock、Condition 的区别吗?”
我(呼吸急促):“额……这个……”
好家伙!这问题我真没准备充分,于是面试官给了我一个温馨提示:“LockSupport 其实是 Java 并发编程中的低级工具,很多高级的并发工具都基于它实现,比如 AQS。”
面试结束后,我深感这个知识点必须掌握透彻,于是疯狂查资料、写代码、做实验,终于把 LockSupport 摸透了!今天,就让我带大家一起深入 LockSupport 的世界,让你在下次面试时能自信回答这道题!
什么是 LockSupport?LockSupport 是 JDK 并发包(java.util.concurrent.locks)中的一个工具类,提供了一组低级的、以线程为单位的阻塞与唤醒方法:
LockSupport.park() 让当前线程阻塞(暂停执行)。
LockSupport.unpark(Thread t) 唤醒指定线程。
它的底层其实是调用 Unsafe 类的 park() 和 unpark() 方法,因此能提供比 Object.wait() 和 Thread.sleep() 更高效、精准的线程控制。
官方定义
LockSupport 是用来创建锁和同步类的基础,它通过使用许可(permit)的概念来实现线程的阻塞和恢复。每个线程都有一个许可,最多只有一个!
LockSupport 的基本用法为了搞懂 LockSupport,我们来看一个简单的代码示例:
运行结果
解析:
park() 让线程进入阻塞状态。
unpark(thread) 唤醒被阻塞的线程。
LockSupport 和其他同步工具的区别(1) vs Object.wait()/notify()
面试官提示的关键点:LockSupport不依赖 synchronized,它是更底层的线程阻塞工具!
(2) vs Condition.await()/signal()
(3) vs Thread.sleep()
LockSupport 的 park() 和 unpark() 是基于许可机制的,每个线程最多只能有一个许可。如果调用 unpark(thread) 时,该线程还没 park(),那么许可就会先存储着,等 park() 了再直接恢复。
代码示例
运行结果
AQS(AbstractQueuedSynchronizer)是 Java 并发包的核心组件,ReentrantLock、Semaphore、CountDownLatch 等工具都是基于它实现的,而 AQS 的线程阻塞和唤醒正是用 LockSupport 来完成的!
AQS 的 park() 实现
AQS 的 unpark() 实现
如果你遇到 LockSupport 相关的面试题,可以这样答:
1、LockSupport 是什么?
LockSupport 是 Java 并发包提供的低级线程阻塞/唤醒工具,不依赖锁。
2、它的底层原理?
底层是 Unsafe.park() 和 Unsafe.unpark(),基于许可机制。
3、与 wait/notify、Condition、sleep 的区别?
不依赖锁,指定线程唤醒,支持先唤醒再阻塞。
4、LockSupport 在 AQS 中的作用?
用于线程的阻塞和唤醒,AQS 通过它管理线程队列。
END学完这篇,你下次面试再遇到 LockSupport 就能胸有成竹了!希望这篇文章能帮到你,别忘了点个赞哦!
关注小米,带你学 Java 并发,面试稳过大厂!
我是小米,一个喜欢分享技术的31岁程序员。如果你喜欢我的文章,欢迎关注我的微信公众号“软件求生”,获取更多技术干货!