深入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 線程的時候把等待的對象導出了。