深入java并发包源码(一)简介
深入java并发包源码(二)AQS的介绍与使用
深入java并发包源码(三)AQS独占方法源码分析
阅读本文章前需要了解 CAS 操作是什么。
首先大致介绍一下需要讲到的几个类,只需要理解这几个类是什么关系即可,后面会有详细解析。
Unsafe :这个类提供了 native 方法,未开源,提供了线程阻塞和唤醒,原子操作等方法。
LockSupport :包装了一层 Unsafe 类,非常类似于代理者模式,将在 Unsafe 类中的线程挂起唤醒等操作导出,避免将 UNSAFE
类引入代码造成复杂性上升,并且降低了耦合。
首先我们看一下以 ReentrantLock 为代表的并发工具与 JUC 底层类的关系。
AQS 类:用 Unsafe 类的 CAS 操作和 LockSupport
来实现锁的等待,具体实现在后面会分析。
ReentrantLock:实现了 Lock 接口,持有自定义的 AQS 内部类,通过 AQS 内部类实现锁的操作,然后将 AQS 映射到 Lock 接口上。
接下来仔细介绍一下这些类的实现
Unsafe
Unsafe 类有相当多的功能,比如内存管理,线程同步,对类和数组进行一些骚操作 。想要获取这个类需要用到利用 Java 反射。本篇文章只介绍一些关于并发的操作。
如果有兴趣可以去看一下这篇博客
方法名 | 功能 |
---|---|
park() | 阻塞线程,可以通过参数控制挂起时间和是否可以被中断 |
unpark() | 唤醒线程 |
compareAndSwapObject | CAS 操作 Object |
compareAndSwapInt | CAS 操作 int |
LockSupport
LockSupport 只是对 Unsafe 类进行封装了而已,下面的方法都是直接调用 UNSAFE 类中的方法。
方法名 | 功能 |
---|---|
park() | 阻塞线程 |
parkNanos(long nanos) | 阻塞线程,在 nanos 毫秒后唤醒 |
parkUntil(long deadline) | 阻塞线程,直到 deadline 时间 |
unpark(Thread thread) | 唤醒处于阻塞状态的线程 |
使用 synchronized 在 dump 线程的时候会带有当前线程正在等待对象的信息,然而使用这些方法得不到这些信息,开发人员疏漏了这点。所以在 LockSupport 在 Java 6 中添加了这几个方法。
方法名 | 功能 |
---|---|
park() | 阻塞线程, |
parkNanos(Object blocker, long nanos) | 阻塞线程,在 nanos 毫秒后唤醒 |
parkUntil(Object blocker,long deadline) | 阻塞线程,直到 deadline 时间 |
unpark(Object blocker,Thread thread) | 唤醒处于阻塞状态的线程 |
blocker 就是当前线程正在等待的对象,使用下面表格的方法就可以把在 dump 线程的时候把等待的对象导出了。