Java的內(nèi)置鎖一直都是備受爭(zhēng)議的,,在JDK 1.6之前,,synchronized這個(gè)重量級(jí)鎖其性能一直都是較為低下,雖然在1.6后,,進(jìn)行大量的鎖優(yōu)化策略(【死磕Java并發(fā)】—–深入分析synchronized的實(shí)現(xiàn)原理),但是與Lock相比synchronized還是存在一些缺陷的:雖然synchronized提供了便捷性的隱式獲取鎖釋放鎖機(jī)制(基于JVM機(jī)制),,但是它卻缺少了獲取鎖與釋放鎖的可操作性,可中斷,、超時(shí)獲取鎖,,且它為獨(dú)占式在高并發(fā)場(chǎng)景下性能大打折扣。 在介紹Lock之前,,我們需要先熟悉一個(gè)非常重要的組件,,掌握了該組件JUC包下面很多問(wèn)題都不在是問(wèn)題了。該組件就是AQS,。 AQS,,AbstractQueuedSynchronizer,即隊(duì)列同步器,。它是構(gòu)建鎖或者其他同步組件的基礎(chǔ)框架(如ReentrantLock,、ReentrantReadWriteLock、Semaphore等),,JUC并發(fā)包的作者(Doug Lea)期望它能夠成為實(shí)現(xiàn)大部分同步需求的基礎(chǔ),。它是JUC并發(fā)包中的核心基礎(chǔ)組件。 AQS解決了子啊實(shí)現(xiàn)同步器時(shí)涉及當(dāng)?shù)拇罅考?xì)節(jié)問(wèn)題,,例如獲取同步狀態(tài),、FIFO同步隊(duì)列,。基于AQS來(lái)構(gòu)建同步器可以帶來(lái)很多好處,。它不僅能夠極大地減少實(shí)現(xiàn)工作,,而且也不必處理在多個(gè)位置上發(fā)生的競(jìng)爭(zhēng)問(wèn)題。 在基于AQS構(gòu)建的同步器中,,只能在一個(gè)時(shí)刻發(fā)生阻塞,,從而降低上下文切換的開(kāi)銷,提高了吞吐量,。同時(shí)在設(shè)計(jì)AQS時(shí)充分考慮了可伸縮行,,因此J.U.C中所有基于AQS構(gòu)建的同步器均可以獲得這個(gè)優(yōu)勢(shì)。 AQS的主要使用方式是繼承,,子類通過(guò)繼承同步器并實(shí)現(xiàn)它的抽象方法來(lái)管理同步狀態(tài),。 AQS使用一個(gè)int類型的成員變量state來(lái)表示同步狀態(tài),當(dāng)state>0時(shí)表示已經(jīng)獲取了鎖,,當(dāng)state = 0時(shí)表示釋放了鎖,。它提供了三個(gè)方法(getState()、setState(int newState),、compareAndSetState(int expect,int update))來(lái)對(duì)同步狀態(tài)state進(jìn)行操作,,當(dāng)然AQS可以確保對(duì)state的操作是安全的。 AQS通過(guò)內(nèi)置的FIFO同步隊(duì)列來(lái)完成資源獲取線程的排隊(duì)工作,,如果當(dāng)前線程獲取同步狀態(tài)失?。ㄦi)時(shí),AQS則會(huì)將當(dāng)前線程以及等待狀態(tài)等信息構(gòu)造成一個(gè)節(jié)點(diǎn)(Node)并將其加入同步隊(duì)列,,同時(shí)會(huì)阻塞當(dāng)前線程,,當(dāng)同步狀態(tài)釋放時(shí),則會(huì)把節(jié)點(diǎn)中的線程喚醒,,使其再次嘗試獲取同步狀態(tài),。 AQS主要提供了如下一些方法:
后面LZ將會(huì)就CLH隊(duì)列,同步狀態(tài)的獲取,、釋放做詳細(xì)介紹 參考資料
|
|
來(lái)自: 關(guān)平藏書 > 《java線程》