有关Java 锁原理
鎖
鎖是用來鎖東西的,讓別人打不開也看不到!在線程中,用這個(gè)“鎖”隱喻來說明一個(gè)線程在“操作”一個(gè)目標(biāo)(如一個(gè)變量)的時(shí)候,如果變量是被鎖住的,那么其他線程就對這個(gè)目標(biāo)既“操作”不了(掛起)也無法看到目標(biāo)的內(nèi)容!對Java并發(fā)包,鎖的實(shí)現(xiàn)基本在java.util.concurrent.locks包中,說“基本”是因?yàn)?#xff0c;在java.util.concurrent中還有CountDownLatch(可以看成帶計(jì)數(shù)器的鎖),CyclicBarrier,Semaphore(類似于信號量,但是也可以看成一個(gè)特殊的鎖)。這里我們先以java.util.concurrent.locks包為主來討論鎖的問題吧。我們來看看java.util.concurrent.locks包中到底有多少“鎖”,主要是這樣幾個(gè)接口及其實(shí)現(xiàn):
Lock----------
??????????????????|---------ReadLock //讀鎖
???????????????? ?|------ReentrantLock??//并發(fā)鎖
??????????????????|------WriteLock //寫鎖
ReadWriteLock----------------
?????????????????????|-------------ReentrantReadWriteLock //并發(fā)讀寫鎖
以上:Lock和ReadWriteLock都是接口,是鎖行為的契約,其余部分都是實(shí)現(xiàn),而ReadLock和WriteLock是作為ReentrantReadWriteLock的靜態(tài)內(nèi)部類存在,不能直接使用,也就是他們是ReentrantReadWriteLock的支持類,不是向外提供給外部程序使用的!
?
另外還發(fā)現(xiàn)有這樣抽象類:
AbstractOwnableSynchronizer---------
?????????????????????????????????????????????????????????|----------AbstractQueuedLongSynchronizer
?????????????????????????????????????????????????????????|-------AbstractQueuedSynchronizer
這幾個(gè)都是抽象類,但是沒有明顯的實(shí)現(xiàn)!沒有實(shí)現(xiàn)?其實(shí)是所有的Lock在其實(shí)現(xiàn)時(shí)使用的基礎(chǔ)結(jié)構(gòu),并且以來它們實(shí)現(xiàn)了鎖的機(jī)制,只要我們先把這幾個(gè)抽象類的實(shí)現(xiàn)邏輯搞清楚,Lock的原理就比較清楚了,理解了原理,使用Lock時(shí)就有的放矢了。
另外包中還有condition接口:
Condition------------
?????????????????????????????|---------?ConditionObject
這個(gè)接口和實(shí)現(xiàn)是干什么的?是用來實(shí)現(xiàn)“競賽條件”的,提供更加細(xì)粒度的線程鎖控制,也就是在某個(gè)條件下加鎖等操作。
?
好了,java.util.concurrent.locks?中的基本“布局”和“結(jié)構(gòu)”現(xiàn)在已經(jīng)比較清楚了,下面我們將從AbstractOwnableSynchronizer抽象類開始講,這是整個(gè)Lock的核心,明白其實(shí)現(xiàn)能讓你了解如何“準(zhǔn)確”的使用鎖,而不是僅僅“知道電視機(jī)的按鈕而不知道里面的原理”,畢竟我們是搞開發(fā)的,對原理更應(yīng)該重視,你說是吧?
AbstractOwnableSynchronizer:
它依靠于CLH隊(duì)列來實(shí)現(xiàn)鎖的機(jī)制
?????*??????+------+??prev +-----+???????+-----+
?????* head |??????| <---- |?????| <---- |?????|??tail
?????*??????+------+???????+-----+???????+-----+
?
采用的CHL模型采用下面的算法完成FIFO的入隊(duì)列和出隊(duì)列過程,而正是入隊(duì)和出隊(duì)的實(shí)現(xiàn)“模擬”了“鎖”的效用!
對于入隊(duì)列(enqueue):采用CAS操作,每次比較尾結(jié)點(diǎn)是否一致,然后插入的到尾結(jié)點(diǎn)中。
?
do {
?
????????pred = tail;
?
}while ( !compareAndSet(pred,tail,node) );
對于出隊(duì)列(dequeue):由于每一個(gè)節(jié)點(diǎn)也緩存了一個(gè)狀態(tài),決定是否出隊(duì)列,因此當(dāng)不滿足條件時(shí)就需要自旋等待,一旦滿足條件就將頭結(jié)點(diǎn)設(shè)置為下一個(gè)節(jié)點(diǎn)。
?
while (pred.status != RELEASED) ;
?
head??= node;
?
有三個(gè)核心字段:
?
private volatile int state;
?
private transient volatile Node head;
?
private transient volatile Node tail;
其中state描述的有多少個(gè)線程取得了鎖,對于互斥鎖來說state<=1。head/tail加上CAS()操作就構(gòu)成了一個(gè)CHL的FIFO隊(duì)列。下面是Node節(jié)點(diǎn)的屬性。
?
volatile int waitStatus;?節(jié)點(diǎn)的等待狀態(tài),一個(gè)節(jié)點(diǎn)可能位于以下幾種狀態(tài):
?
CANCELLED = 1:?節(jié)點(diǎn)操作因?yàn)槌瑫r(shí)或者對應(yīng)的線程被interrupt。節(jié)點(diǎn)不應(yīng)該不留在此狀態(tài),一旦達(dá)到此狀態(tài)將從CHL隊(duì)列中踢出。
SIGNAL = -1:?節(jié)點(diǎn)的繼任節(jié)點(diǎn)是(或者將要成為)BLOCKED狀態(tài)(例如通過LockSupport.park()操作),因此一個(gè)節(jié)點(diǎn)一旦被釋放(解鎖)或者取消就需要喚醒(LockSupport.unpack())它的繼任節(jié)點(diǎn)。
CONDITION = -2:表明節(jié)點(diǎn)對應(yīng)的線程因?yàn)椴粷M足一個(gè)條件(Condition)而被阻塞。
0:?正常狀態(tài),新生的非CONDITION節(jié)點(diǎn)都是此狀態(tài)。
非負(fù)值標(biāo)識節(jié)點(diǎn)不需要被通知(喚醒)。
volatile Node prev;此節(jié)點(diǎn)的前一個(gè)節(jié)點(diǎn)。節(jié)點(diǎn)的waitStatus依賴于前一個(gè)節(jié)點(diǎn)的狀態(tài)。
?
volatile Node next;此節(jié)點(diǎn)的后一個(gè)節(jié)點(diǎn)。后一個(gè)節(jié)點(diǎn)是否被喚醒(uppark())依賴于當(dāng)前節(jié)點(diǎn)是否被釋放。
?
volatile Thread thread;節(jié)點(diǎn)綁定的線程。
?
Node nextWaiter;下一個(gè)等待條件(Condition)的節(jié)點(diǎn),由于Condition是獨(dú)占模式,因此這里有一個(gè)簡單的隊(duì)列來描述Condition上的線程節(jié)點(diǎn)。
以上只是一個(gè)簡單的描述吧,只要知道AbstractOwnableSynchronizer的核心是一個(gè)CHL隊(duì)列,而AbstractOwnableSynchronizer是所有Lock的基礎(chǔ),在講具體Lock的時(shí)候,我將“回溯”到AbstractOwnableSynchronizer,凡是具體Lock調(diào)用AbstractOwnableSynchronizer的方法的時(shí)候,我將具體講一下其實(shí)現(xiàn),并對應(yīng)著Lock對應(yīng)方法的實(shí)現(xiàn),這樣就能徹底搞清楚具體Lock的原理了,也就能在使用時(shí)游刃有余了。
對于那些真正需要探知Lock一切底細(xì)的家伙而言,我找了個(gè)文檔,作為附件,是并發(fā)作者的論文,不過你需要英文好一些才可以哦
轉(zhuǎn)載于:https://www.cnblogs.com/isoftware/p/3794996.html
總結(jié)
以上是生活随笔為你收集整理的有关Java 锁原理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: setInterval和setTimeo
- 下一篇: java美元兑换,(Java实现) 美元