LockSupport详解

LockSupport是Java中的一个线程工具类,提供了park和unpark方法来阻塞和唤醒线程,与wait/notify相比,它无需锁定对象即可操作,并能指定唤醒特定线程。在源码层面,park方法会消耗“许可”,而unpark则是生产“许可”。通过LockSupport,我们可以更灵活地控制线程的执行流程。

LockSupport是一个编程工具类,主要是为了阻塞和唤醒线程用的。使用它我们可以实现很多功能,今天主要就是对这个工具类的讲解,希望对你有帮助:

一、LockSupport简介

1、LockSupport是什么

刚刚开头提到过,LockSupport是一个线程工具类,所有的方法都是静态方法,可以让线程在任意位置阻塞,也可以在任意位置唤醒。

它的内部其实两类主要的方法:park(停车阻塞线程)和unpark(启动唤醒线程)。

注意上面的123方法,都有一个blocker,这个blocker是用来记录线程被阻塞时被谁阻塞的。用于线程监控和分析工具来定位原因的。

现在我们知道了LockSupport是用来阻塞和唤醒线程的,而且之前相信我们都知道wait/notify也是用来阻塞和唤醒线程的,那么它相比,LockSupport有什么优点呢?

2、与wait/notify对比

这里假设你已经了解了wait/notify的机制,如果不了解,可以在网上一搜,很简单。相信你既然学到了这个LockSupport,相信你已经提前已经学了wait/notify。

我们先来举一个使用案例:

上面这段代码的意思是,我们定义一个线程,但是在内部进行了park,因此需要unpark才能唤醒继续执行,不过上面,我们在MyThread进行的park,在main线程进行的unpark。

这样来看,好像和wait/notify没有什么区别。那他的区别到底是什么呢?这个就需要仔细的观察了。这里主要有两点:

(1)wait和notify都是Object中的方法,在调用这两个方法前必须先获得锁对象,但是park不需要获取某个对象的锁就可以锁住线程。

(2)notify只能随机选择一个线程唤醒,无法唤醒指定的线程,unpark却可以唤醒一个指定的线程。

区别就是这俩,还是主要从park和unpark的角度来解释的。既然这个LockSupport这么强,我们就深入一下他的源码看看。

二、源码分析(基于jdk1.8)

1、park方法

blocker是用来记录线程被阻塞时被谁阻塞的。用于线程监控和分析工具来定位原因的。setBlocker(t, blocker)方法的作用是记录t线程是被broker阻塞的。因此我们只关注最核心的方法,也就是UNSAFE.park(false, 0L)。

UNSAFE是一个非常强大的类,他的的操作是基于底层的,也就是可以直接操作内存,因此我们从JVM的角度来分析一下:

每个java线程都有一个Parker实例:

我们换一种角度来理解一下park和unpark,可以想一下,unpark其实就相当于一个许可,告诉特定线程你可以停车,特定线程想要park停车的时候一看到有许可,就可以立马停车继续运行了。因此其执行顺序可以颠倒。

现在有了这个概念,我们体会一下上面JVM层面park的方法,这里面counter字段,就是用来记录所谓的“许可”的。

本文部分总结来源于:https://www.jianshu.com/p/1f16b838ccd8

 

这就是整个park的过程,总结来说就是消耗“许可”的过程。

2、unpark

还是先来看一下JDK源码:

上面注释的意思是给线程生产许可证。

当unpark时,则简单多了,直接设置_counter为1,再unlock mutext返回。如果_counter之前的值是0,则还要调用pthread_cond_signal唤醒在park中等待的线程:

ok,现在我们已经对源码进行了分析,整个过程其实就是生产许可和消费许可的过程。而且这个生产过程可以反过来。也就是先生产再消费。下面我们使用几个例子验证一波。

三、LockSupport使用

1、先interrupt再park

我们看一下结果:

 

2、先unpark再park

 

### LockSupport 的详细信息和使用方法 LockSupportJava 并发包中的一个工具类,主要用于线程的阻塞与唤醒操作。它的核心功能是通过 `park` 和 `unpark` 方法实现线程的暂停与恢复。以下是关于 LockSupport 的详细信息和使用方法: #### 1. 基本概念 LockSupport 提供了一个轻量级的线程阻塞机制,其底层依赖于 Unsafe 类的 `park` 和 `unpark` 操作[^4]。每个线程都有一个许可(permit),当调用 `park` 方法时,线程会检查是否有可用的许可。如果没有许可,线程将进入等待状态;如果有许可,则消耗该许可并继续执行。 #### 2. 核心方法 LockSupport 提供了以下两个主要方法: - **`public static void park(Object blocker)`**:使当前线程进入阻塞状态,直到其他线程调用 `unpark` 或发生中断。 - **`public static void unpark(Thread thread)`**:为指定线程提供一个许可,使其从阻塞状态中唤醒。 #### 3. 使用示例 以下是一个简单的代码示例,展示如何使用 LockSupport 实现线程的阻塞与唤醒: ```java public class LockSupportExample { public static void main(String[] args) throws InterruptedException { Thread worker = new Thread(() -> { System.out.println("Worker thread is parking."); LockSupport.park(); // 阻塞当前线程 System.out.println("Worker thread is unparked."); }); worker.start(); Thread.sleep(1000); // 主线程休眠1秒,确保worker线程先运行 System.out.println("Main thread is calling unpark."); LockSupport.unpark(worker); // 唤醒worker线程 } } ``` #### 4. 特性与注意事项 - **许可的可传递性**:如果在调用 `park` 之前已经调用了 `unpark`,则许可会被保存,并在后续的 `park` 调用中立即生效。 - **线程安全性**:LockSupport 的操作是线程安全的,适合用于复杂的并发场景。 - **性能优化**:LockSupport 的设计目的是为了高效地实现线程的阻塞与唤醒,避免传统锁机制带来的开销。 #### 5. 底层原理 LockSupport 的底层实现基于 Unsafe 类的 `park` 和 `unpark` 方法。`park` 方法通过操作系统提供的原生接口使线程进入等待状态,而 `unpark` 则通过设置线程的许可标志位来唤醒线程[^4]。 ### 示例应用场景 LockSupport 常用于构建自定义的同步工具,例如 AQS(AbstractQueuedSynchronizer)的实现。AQS 使用 LockSupport 来管理线程的阻塞与唤醒,从而实现高效的锁机制[^4]。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值