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

扒一扒ReentrantLock以及AQS實現原理

開發 架構
這篇文章,就用最簡單的大白話配合N多張手繪圖,給大家講清楚AQS到底是什么?讓各位同學面試被問到這個問題時,不至于不知所措。

這篇文章,我們來聊聊面試的時候比較有殺傷力的一個問題:聊聊你對AQS的理解?

之前有同學反饋,去互聯網公司面試,面試官聊到并發時就問到了這個問題。當時那位同學內心估計受到了一萬點傷害。。。

因為首先,很多人還真的連AQS是什么都不知道,可能聽都沒聽說過?;蛘哂械娜寺犝f過AQS這個名詞,但是可能連具體全稱怎么拼寫都不知道。

更有甚者,可能會說:AQS?是不是一種思想?我們平時開發怎么來用AQS?

總體來說,很多同學估計都對AQS有一種云里霧里的感覺,如果用搜索引擎查一下AQS是什么?看幾篇文章,估計就直接放棄了,因為密密麻麻的文字,實在是看不懂!

所以,基于上述痛點,咱們這篇文章,就用最簡單的大白話配合N多張手繪圖,給大家講清楚AQS到底是什么?讓各位同學面試被問到這個問題時,不至于不知所措。

ReentrantLock和AQS的關系

首先我們來看看,如果用Java并發包下的ReentrantLock來加鎖和釋放鎖,是個什么樣的感覺?

這個基本學過Java的同學應該都會吧,畢竟這個是java并發基本API的使用,應該每個人都是學過的,所以我們直接看一下代碼就好了:

扒一扒ReentrantLock以及AQS實現原理

上面那段代碼應該不難理解吧,無非就是搞一個Lock對象,然后加鎖和釋放鎖。

你這時可能會問,這個跟AQS有啥關系?關系大了去了!因為Java并發包下很多API都是基于AQS來實現的加鎖和釋放鎖等功能的,AQS是Java并發包的基礎類。

舉個例子,比如說ReentrantLock、ReentrantReadWriteLock底層都是基于AQS來實現的。

那么AQS的全稱是什么呢?AbstractQueuedSynchronizer,抽象隊列同步器。給大家畫一個圖先,看一下ReentrantLock和AQS之間的關系。

扒一扒ReentrantLock以及AQS實現原理

我們來看上面的圖。說白了,ReentrantLock內部包含了一個AQS對象,也就是
AbstractQueuedSynchronizer類型的對象。這個AQS對象就是ReentrantLock可以實現加鎖和釋放鎖的關鍵性的核心組件。

ReentrantLock加鎖和釋放鎖的底層原理

好了,那么現在如果有一個線程過來嘗試用ReentrantLock的lock()方法進行加鎖,會發生什么事情呢?

很簡單,這個AQS對象內部有一個核心的變量叫做state,是int類型的,代表了加鎖的狀態。初始狀態下,這個state的值是0。

另外,這個AQS內部還有一個關鍵變量,用來記錄當前加鎖的是哪個線程,初始化狀態下,這個變量是null。

扒一扒ReentrantLock以及AQS實現原理

接著線程1跑過來調用ReentrantLock的lock()方法嘗試進行加鎖,這個加鎖的過程,直接就是用CAS操作將state值從0變為1。

如果不知道CAS是啥的,請看上篇文章,《??Java8中的LongAdder類,大大提升CAS性能??!》。

如果之前沒人加過鎖,那么state的值肯定是0,此時線程1就可以加鎖成功。

一旦線程1加鎖成功了之后,就可以設置當前加鎖線程是自己。所以大家看下面的圖,就是線程1跑過來加鎖的一個過程。

扒一扒ReentrantLock以及AQS實現原理

其實看到這兒,大家應該對所謂的AQS有感覺了。說白了,就是并發包里的一個核心組件,里面有state變量、加鎖線程變量等核心的東西,維護了加鎖狀態。

你會發現,ReentrantLock這種東西只是一個外層的API,內核中的鎖機制實現都是依賴AQS組件的。

這個ReentrantLock之所以用Reentrant打頭,意思就是他是一個可重入鎖。

可重入鎖的意思,就是你可以對一個ReentrantLock對象多次執行lock()加鎖和unlock()釋放鎖,也就是可以對一個鎖加多次,叫做可重入加鎖。

大家看明白了那個state變量之后,就知道了如何進行可重入加鎖!

其實每次線程1可重入加鎖一次,會判斷一下當前加鎖線程就是自己,那么他自己就可以可重入多次加鎖,每次加鎖就是把state的值給累加1,別的沒啥變化。

接著,如果線程1加鎖了之后,線程2跑過來加鎖會怎么樣呢?

我們來看看鎖的互斥是如何實現的?線程2跑過來一下看到,哎呀!state的值不是0?。克訡AS操作將state從0變為1的過程會失敗,因為state的值當前為1,說明已經有人加鎖了!

接著線程2會看一下,是不是自己之前加的鎖?。慨斎徊皇橇?,“加鎖線程”這個變量明確記錄了是線程1占用了這個鎖,所以線程2此時就是加鎖失敗。

給大家來一張圖,一起來感受一下這個過程:

扒一扒ReentrantLock以及AQS實現原理

接著,線程2會將自己放入AQS中的一個等待隊列,因為自己嘗試加鎖失敗了,此時就要將自己放入隊列中來等待,等待線程1釋放鎖之后,自己就可以重新嘗試加鎖了

所以大家可以看到,AQS是如此的核心!AQS內部還有一個等待隊列,專門放那些加鎖失敗的線程!

同樣,給大家來一張圖,一起感受一下:

扒一扒ReentrantLock以及AQS實現原理

接著,線程1在執行完自己的業務邏輯代碼之后,就會釋放鎖!他釋放鎖的過程非常的簡單,就是將AQS內的state變量的值遞減1,如果state值為0,則徹底釋放鎖,會將“加鎖線程”變量也設置為null!

整個過程,參見下圖:

扒一扒ReentrantLock以及AQS實現原理

接下來,會從等待隊列的隊頭喚醒線程2重新嘗試加鎖。

好!線程2現在就重新嘗試加鎖,這時還是用CAS操作將state從0變為1,此時就會成功,成功之后代表加鎖成功,就會將state設置為1。

此外,還要把“加鎖線程”設置為線程2自己,同時線程2自己就從等待隊列中出隊了。

最后再來一張圖,大家來看看這個過程。

扒一扒ReentrantLock以及AQS實現原理

總結

OK,本文到這里為止,基本借著ReentrantLock的加鎖和釋放鎖的過程,給大家講清楚了其底層依賴的AQS的核心原理。

基本上大家把這篇文章看懂,以后再也不會擔心面試的時候被問到:談談你對AQS的理解這種問題了。

其實一句話總結AQS就是一個并發包的基礎組件,用來實現各種鎖,各種同步組件的。它包含了state變量、加鎖線程、等待隊列等并發中的核心組件。

責任編輯:姜華 來源: 今日頭條
相關推薦

2025-06-04 01:20:00

2019-10-21 10:59:52

編程語言JavaC

2023-04-10 23:05:54

NacosOpenFeignRibbon

2019-02-25 22:46:39

2019-09-10 07:29:44

2018-04-03 15:42:40

2023-01-30 22:10:12

BeanSpring容器

2024-12-04 13:54:19

pnpm存儲項目

2020-01-15 15:29:52

InnoDB數據硬盤

2015-09-16 14:04:06

大數據巨頭

2015-10-15 13:38:39

2015-08-18 09:12:54

app推廣渠道

2019-01-03 11:09:19

2015-09-21 10:07:31

2015-09-16 14:11:47

2017-09-07 18:45:51

C#

2021-05-13 05:25:16

數據分析數分培訓大數據

2025-04-30 07:26:04

2022-09-30 09:40:39

智能汽車

2019-04-28 14:24:54

吳亦凡流量數據
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产做爰 | 欧美精品一区二区在线观看 | 亚洲国产精品久久久久秋霞不卡 | 青青草国产在线观看 | 成人片免费看 | 中文字幕不卡视频在线观看 | 在线免费国产 | 亚洲视频一 | 国产精品久久久久久婷婷天堂 | 久久久久国产精品 | 亚洲精品久久久久久国产精华液 | 激情久久久久 | 97国产在线视频 | 天天操网| 午夜在线 | 亚洲精品一区中文字幕乱码 | 欧美成人一区二区三区片免费 | 成人黄色电影免费 | 国产在线精品一区二区三区 | 天天在线操 | 久久免费精品 | 二区av| 亚洲欧美少妇 | 超碰日韩 | 古典武侠第一页久久777 | 精品日韩一区二区 | 欧美日韩国产精品激情在线播放 | 国产欧美精品一区二区 | 日本中出视频 | 欧美精品一 | 国产欧美精品 | 成人一区二区三区视频 | 国产精品视频免费观看 | 久久久久久综合 | 91人人视频在线观看 | 精品国产一区二区三区久久 | 精品国产乱码久久久 | 欧美在线一区二区三区 | 午夜一区二区三区 | 国产精品免费观看 | 欧美一级久久久猛烈a大片 日韩av免费在线观看 |