成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

干貨,深入剖析ReentrantLock源碼,推薦收藏

開發 前端
看完了ReentrantLock的所有源碼,是不是覺得ReentrantLock很簡單。由于加鎖流程的編排工作已經在父類AQS中實現,子類只需要實現具體的加鎖邏輯即可。

ReentrantLock和Synchronized都是Java開發中最常用的鎖,與Synchronized這種JVM內置鎖不同的是,ReentrantLock提供了更豐富的語義。可以創建公平鎖或非公平鎖、響應中斷、超時等待、按條件喚醒等。在某些場景下,使用ReentrantLock更適合,功能更強大。

前兩篇文章,我們分析了AQS的加鎖流程、以及源碼實現。當時我們就說了,AQS使用了模板設計模式,父類中定義加鎖流程,子類去實現具體的加鎖邏輯。所以大部分加鎖代碼已經在父類AQS中實現了,導致ReentrantLock的源碼非常簡單,一塊學習一下。

先看一下ReentrantLock怎么使用?

1. ReentrantLock的使用

/**
* @author 一燈架構
* @apiNote ReentrantLock示例
**/
public class ReentrantLockDemo {

public static void main(String[] args){
// 1. 創建ReentrantLock對象
ReentrantLock lock = new ReentrantLock();
// 2. 加鎖
lock.lock();
try {
// 3. 這里執行具體的業務邏輯
} finally {
// 4. 釋放鎖
lock.unlock();
}
}
}

可以看到ReentrantLock的使用非常簡單,調用lock加鎖,unlock釋放鎖,需要配置try/finally使用,保證在代碼執行出錯的時候也能釋放鎖。

ReentrantLock也可以配合Condition條件使用,具體可以翻一下前幾篇文章中BlockingQueue的源碼解析,那里面有ReentrantLock的實際使用。

再看一下ReentrantLock的類結構

2. ReentrantLock類結構

// 實現Lock接口
public class ReentrantLock implements Lock {

// 只有一個Sync同步變量
private final Sync sync;

// Sync繼承自AQS,主要邏輯都在這里面
abstract static class Sync extends AbstractQueuedSynchronizer {
}

// Sync的兩個子類,分別實現了公平鎖和非公平鎖
static final class FairSync extends Sync {
}
static final class NonfairSync extends Sync {
}

}

可以看出ReentrantLock的類結構非常簡單,實現了Lock接口。

類里面有兩個靜態內部類,分別實現公平鎖和非公平鎖。

看一下Lock接口中,定義了哪些方法?

public interface Lock {

// 加鎖
void lock();

// 加可中斷的鎖
void lockInterruptibly() throws InterruptedException;

// 嘗試加鎖
boolean tryLock();

// 一段時間內,嘗試加鎖
boolean tryLock(long time, TimeUnit unit) throws InterruptedException;

// 釋放鎖
void unlock();

// 新建條件狀態
Condition newCondition();
}

就是一些使用鎖的常用方法。

在上篇文章中瀏覽AQS源碼的時候,了解到AQS定義了一些有關具體加鎖、釋放鎖的抽象方法,留給子類去實現,再看一下有哪些抽象方法:

// 加獨占鎖
protected boolean tryAcquire(int arg){
throw new UnsupportedOperationException();
}
// 釋放獨占鎖
protected boolean tryRelease(int arg){
throw new UnsupportedOperationException();
}

// 加共享鎖
protected int tryAcquireShared(int arg){
throw new UnsupportedOperationException();
}
// 釋放共享鎖
protected boolean tryReleaseShared(int arg){
throw new UnsupportedOperationException();
}

// 判斷是否是當前線程正在持有鎖
protected boolean isHeldExclusively(){
throw new UnsupportedOperationException();
}

由于ReentrantLock使用的是獨占鎖,所以只需要實現獨占鎖相關的方法就可以了。

3.ReentrantLock源碼解析

3.1 ReentrantLock構造方法

// 默認的構造方法,使用非公平鎖
public ReentrantLock(){
sync = new NonfairSync();
}

// 傳true,可以指定使用公平鎖
public ReentrantLock(boolean fair){
sync = fair ? new FairSync() : new NonfairSync();
}

在創建ReentrantLock對象的時候,可以指定使用公平鎖還是非公平鎖,默認使用非公平鎖,顯然非公平鎖的性能更好。

先思考一個面試常考問題,公平鎖和非公平鎖是怎么實現的?

3.2 非公平鎖源碼

先看一下加鎖源碼:

從父類ReentrantLock的加鎖方法入口:

public class ReentrantLock implements Lock {
// 加鎖入口方法
public void lock(){
// 調用Sync中加鎖方法
sync.lock();
}
}

在子類NonfairSync的加鎖方法:

// 非公平鎖
static final class NonfairSync extends Sync {

// 加鎖
final void lock(){
// 1. 先嘗試加鎖(使用CAS設置state=1
if (compareAndSetState(0, 1))
// 2. 加鎖成功,就把當前線程設置為持有鎖線程
setExclusiveOwnerThread(Thread.currentThread());
else
// 3. 沒加鎖成功,再調用父類AQS中實際的加鎖邏輯
acquire(1);
}
}

加鎖邏輯也很簡單,先嘗試使用CAS加鎖(也就是把state從0設置成1),加鎖成功,就把當前線程設置為持有鎖線程。

設計者很聰明,在鎖競爭不激烈的情況下,很大概率可以加鎖成功,也就不用走else中復雜的加鎖邏輯了。

如果沒有加鎖成功,還是需要走else中調用父類AQS的acquire方法,而acquire又需要調用子類的tryAcquire方法。

調用鏈路就是下面這樣:

圖片

根據調用鏈路,實際的加鎖邏輯在Sync.nonfairTryAcquire方法里面。

abstract static class Sync extends AbstractQueuedSynchronizer {
// 非公平鎖的最終加鎖方法
final boolean nonfairTryAcquire(int acquires){
final Thread current = Thread.currentThread();
// 1. 獲取同步狀態
int c = getState();
// 2. state=0表示無鎖,先嘗試加鎖(使用CAS設置state=1
if (c == 0) {
if (compareAndSetState(0, acquires)) {
// 3. 加鎖成功,就把當前線程設置為持有鎖線程
setExclusiveOwnerThread(current);
return true;
}
// 4. 如果當前線程已經持有鎖,執行可重入的邏輯
} else if (current == getExclusiveOwnerThread()) {
// 5. 加鎖次數+acquires
int nextc = c + acquires;
// 6. 超過tnt類型最大值,溢出了
if (nextc < 0)
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
}

再看一下釋放鎖的調用流程,公平鎖和非公平鎖流程是一樣的,最終都是執行Sync.tryRelease方法:

圖片

abstract static class Sync extends AbstractQueuedSynchronizer {
// 釋放鎖
protected final boolean tryRelease(int releases){
// 1. 同步狀態減去釋放鎖次數
int c = getState() - releases;
// 2. 校驗當前線程不持有鎖,就報錯
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
// 3. 判斷同步狀態是否等于0,無鎖后,就刪除持有鎖的線程
if (c == 0) {
free = true;
setExclusiveOwnerThread(null);
}
setState(c);
return free;
}
}

再看一下公平鎖的源碼

3.3 公平鎖源碼

先看一下公平鎖的加鎖流程:

圖片

最終的加鎖方法是FairSync.tryAcquire,看一下具體邏輯:

static final class FairSync extends Sync {

// 實現父類的加鎖邏輯
protected final boolean tryAcquire(int acquires){
final Thread current = Thread.currentThread();
// 1. 獲取同步狀態
int c = getState();
// 2. state=0表示無鎖,先嘗試加鎖(使用CAS設置state=1
if (c == 0) {
// 3. 判斷當前線程是不是頭節點的下一個節點(講究先來后到)
if (!hasQueuedPredecessors() &&
compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
// 4. 如果當前線程已經持有鎖,執行可重入的邏輯
} else if (current == getExclusiveOwnerThread()) {
// 5. 加鎖次數+acquires
int nextc = c + acquires;
// 6. 超過tnt類型最大值,溢出了
if (nextc < 0)
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}

// 判斷當前線程是不是頭節點的下一個節點(講究先來后到)
public final boolean hasQueuedPredecessors(){
Node t = tail;
Node h = head;
Node s;
return h != t &&
((s = h.next) == null || s.thread != Thread.currentThread());
}
}

公平鎖的釋放鎖邏輯跟非公平鎖一樣,上面已經講過。

4. 總結

看完了ReentrantLock的所有源碼,是不是覺得ReentrantLock很簡單。

由于加鎖流程的編排工作已經在父類AQS中實現,子類只需要實現具體的加鎖邏輯即可。

加鎖邏輯也很簡單,也就是修改同步狀態state的值和持有鎖的線程exclusiveOwnerThread。

責任編輯:武曉燕 來源: 一燈架構
相關推薦

2020-08-24 08:13:25

非公平鎖源碼

2024-04-29 09:06:46

線程初始化源碼

2021-03-06 22:41:06

內核源碼CAS

2020-11-09 07:29:12

ReentrantLo源碼公平鎖

2024-01-29 15:54:41

Java線程池公平鎖

2009-09-27 17:13:36

Hibernate V

2011-06-03 13:48:18

JavaScript重構

2010-06-03 13:08:51

2009-07-06 10:44:45

JSP charset

2009-09-14 15:12:40

LINQ to XML

2010-05-25 12:59:00

Subversion

2022-11-11 10:48:55

AQS源碼架構

2021-05-11 14:50:21

ReentrantLo可重入鎖Java

2010-05-27 10:23:01

SVN文檔

2010-06-30 16:00:01

FTP協議

2010-06-12 14:35:46

UML對象圖

2009-09-25 09:36:55

Hibernate核心

2010-08-04 13:52:53

Flex事件機制

2010-05-27 12:58:07

SVN升級

2019-04-18 10:00:29

Windows實用軟件
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 超碰成人免费 | 亚洲精品日韩精品 | 久久精品国产一区 | 久久国产精品72免费观看 | 中文无吗 | 国产日韩一区二区三免费高清 | 欧美一区二区免费电影 | 欧美一级二级在线观看 | 一区二区在线看 | 精品视频免费 | 国产欧美精品区一区二区三区 | 三级在线免费 | 国产你懂的在线观看 | 色婷婷综合久久久中字幕精品久久 | 亚洲一二三在线观看 | 国产亚洲欧美在线视频 | 中文字幕第5页 | 中文字幕一区二区三区精彩视频 | 欧美午夜一区二区三区免费大片 | 亚洲一二三区在线观看 | 免费成人在线网站 | www.日本在线观看 | 国产精品污www一区二区三区 | 亚洲精品欧美一区二区三区 | 国产精品一区二区久久久久 | 国产成人精品一区二区 | 91观看| 欧美日韩一本 | 99久久婷婷国产综合精品电影 | 欧美久久久久久 | 99精品国产一区二区三区 | 我要看黄色录像一级片 | 中文字幕亚洲视频 | 欧美成人在线免费 | 国产精品久久久久久一区二区三区 | 黑人精品欧美一区二区蜜桃 | 国产精品揄拍一区二区久久国内亚洲精 | 亚洲精品乱码久久久久久按摩观 | 欧美综合久久 | 免费毛片www com cn | 日韩一区在线视频 |