掃二維碼與項(xiàng)目經(jīng)理溝通
我們?cè)谖⑿派?4小時(shí)期待你的聲音
解答本文疑問(wèn)/技術(shù)咨詢/運(yùn)營(yíng)咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流
在并發(fā)多線程的情況下,為了保證數(shù)據(jù)安全性,一般我們會(huì)對(duì)數(shù)據(jù)進(jìn)行加鎖,通常使用Synchronized或者ReentrantLock同步鎖。Synchronized是基于JVM實(shí)現(xiàn),而ReentrantLock是基于Java代碼層面實(shí)現(xiàn)的,底層是繼承的AQS。

成都創(chuàng)新互聯(lián)專注于章丘網(wǎng)站建設(shè)服務(wù)及定制,我們擁有豐富的企業(yè)做網(wǎng)站經(jīng)驗(yàn)。 熱誠(chéng)為您提供章丘營(yíng)銷型網(wǎng)站建設(shè),章丘網(wǎng)站制作、章丘網(wǎng)頁(yè)設(shè)計(jì)、章丘網(wǎng)站官網(wǎng)定制、小程序設(shè)計(jì)服務(wù),打造章丘網(wǎng)絡(luò)公司原創(chuàng)品牌,更為您提供章丘網(wǎng)站排名全網(wǎng)營(yíng)銷落地服務(wù)。
AQS全稱**AbstractQueuedSynchronizer**,即抽象隊(duì)列同步器,是一種用來(lái)構(gòu)建鎖和同步器的框架。
我們常見的并發(fā)鎖ReentrantLock、CountDownLatch、Semaphore、CyclicBarrier都是基于AQS實(shí)現(xiàn)的,所以說(shuō)不懂AQS實(shí)現(xiàn)原理的,就不能說(shuō)了解Java鎖。
當(dāng)我仔細(xì)研究AQS底層加鎖原理,發(fā)現(xiàn)竟然跟Synchronized加鎖原理有驚人的相似。讓我突然想到一句名言,記不清怎么說(shuō)了,意思是框架底層原理很相似,大家多學(xué)習(xí)底層原理。
Synchronized的加鎖流程在前幾篇文章已經(jīng)詳細(xì)講過(guò),沒(méi)看過(guò)一塊再溫習(xí)一下。
我們先想一下Synchronized的加鎖需求,如果讓你設(shè)計(jì)Synchronized的對(duì)象鎖存儲(chǔ)結(jié)構(gòu),該怎么設(shè)計(jì)?
上面描述了Synchronized的加鎖流程,Synchronized的對(duì)象鎖存儲(chǔ)結(jié)構(gòu)是不是跟咱們想的一樣?實(shí)際就是的。
下面是對(duì)象鎖的存儲(chǔ)數(shù)據(jù)結(jié)構(gòu)(由C++實(shí)現(xiàn)):
ObjectMonitor() {
_header = NULL;
_count = 0;
_waiters = 0,
_recursions = 0;
_object = NULL;
_owner = NULL; // 持有鎖的線程
_WaitSet = NULL; // 等待隊(duì)列,存儲(chǔ)處于wait狀態(tài)的線程
_WaitSetLock = 0 ;
_Responsible = NULL ;
_succ = NULL ;
_cxq = NULL ;
FreeNext = NULL ;
_EntryList = NULL ; // 阻塞隊(duì)列,存儲(chǔ)處于等待鎖block狀態(tài)的線程
_SpinFreq = 0 ;
_SpinClock = 0 ;
OwnerIsThread = 0 ;
}上圖展示了對(duì)象鎖的基本工作機(jī)制:
Synchronized對(duì)象鎖存儲(chǔ)結(jié)構(gòu)和加鎖流程,竟然跟咱們想的一樣。
再看一下AQS的存儲(chǔ)結(jié)構(gòu)和加鎖流程,有沒(méi)有相似的地方。
先分析一下,我們使用AQS的加鎖需求:
AQS的需求跟Synchronized一模一樣。
我們?cè)倏匆幌翧QS實(shí)際的加鎖機(jī)制是怎么設(shè)計(jì)的?是不是跟Synchronized相似?
AQS的加鎖流程并不復(fù)雜,只要理解了同步隊(duì)列和條件隊(duì)列,以及它們之間的數(shù)據(jù)流轉(zhuǎn),就算徹底理解了AQS。
可以看到AQS和Synchronized的加鎖流程幾乎是一模一樣的,AQS中同步隊(duì)列就是Synchronized中EntryList,AQS中條件隊(duì)列就是Synchronized中的waitSet,兩個(gè)隊(duì)列之間的數(shù)據(jù)轉(zhuǎn)移流程也是一樣的。
AQS跟Synchronized的加鎖流程是一樣的,都是通過(guò)同步隊(duì)列和條件隊(duì)列實(shí)現(xiàn)的,阻塞狀態(tài)的線程被放到同步隊(duì)列中,等待狀態(tài)的線程被放到條件隊(duì)列中,從條件隊(duì)列喚醒的線程又被轉(zhuǎn)移到同步隊(duì)列末尾,一塊競(jìng)爭(zhēng)鎖。
看完AQS加鎖流程,還沒(méi)有人不懂AQS的?
下篇文章再講一下AQS加鎖具體的源碼實(shí)現(xiàn)。里面有很多精巧的設(shè)計(jì),值得我們學(xué)習(xí)。
比如:
為什么同步隊(duì)列要設(shè)計(jì)成雙向鏈表?而條件隊(duì)列要設(shè)計(jì)成單鏈表?
為什么AQS加鎖性能這么好(樂(lè)觀鎖CAS使用)?
同步隊(duì)列和條件隊(duì)列中節(jié)點(diǎn)怎么用一個(gè)對(duì)象實(shí)現(xiàn)?
釋放鎖后,怎么喚醒同步隊(duì)列中線程?

我們?cè)谖⑿派?4小時(shí)期待你的聲音
解答本文疑問(wèn)/技術(shù)咨詢/運(yùn)營(yíng)咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流