java中的账户冻结原理_java可重入锁(ReentrantLock)的实现原理
前言
相信學(xué)過java的人都知道 synchronized 這個(gè)關(guān)鍵詞,也知道它用于控制多線程對(duì)并發(fā)資源的安全訪問,興許,你還用過Lock相關(guān)的功能,但你可能從來沒有想過java中的鎖底層的機(jī)制是怎么實(shí)現(xiàn)的。如果真是這樣,而且你有興趣了解,今天我將帶領(lǐng)你輕松的學(xué)習(xí)下java中非常重要,也非常基礎(chǔ)的可重入鎖-ReentrantLock的實(shí)現(xiàn)機(jī)制。
聽故事把知識(shí)掌握了
在一個(gè)村子里面,有一口井水,水質(zhì)非常的好,村民們都想打井里的水。這井只有一口,村里的人那么多,所以得出個(gè)打水的規(guī)則才行。村長絞盡腦汁,最終想出了一個(gè)比較合理的方案,咱們來仔細(xì)的看看聰明的村長大人的智慧。
井邊安排一個(gè)看井人,維護(hù)打水的秩序。
打水時(shí),以家庭為單位,哪個(gè)家庭任何人先到井邊,就可以先打水,而且如果一個(gè)家庭占到了打水權(quán),其家人這時(shí)候過來打水不用排隊(duì)。而那些沒有搶占到打水權(quán)的人,一個(gè)一個(gè)挨著在井邊排成一隊(duì),先到的排在前面。打水示意圖如下 :
是不是感覺很和諧,如果打水的人打完了,他會(huì)跟看井人報(bào)告,看井人會(huì)讓第二個(gè)人接著打水。這樣大家總都能夠打到水。是不是看起來挺公平的,先到的人先打水,當(dāng)然不是絕對(duì)公平的,自己看看下面這個(gè)場景 :
看著,一個(gè)有娃的父親正在打水,他的娃也到井邊了,所以女憑父貴直接排到最前面打水,羨煞旁人了。
以上這個(gè)故事模型就是所謂的公平鎖模型,當(dāng)一個(gè)人想到井邊打水,而現(xiàn)在打水的人又不是自家人,這時(shí)候就得乖乖在隊(duì)列后面排隊(duì)。
事情總不是那么一帆風(fēng)順的,總會(huì)有些人想走捷徑,話說看井人年紀(jì)大了,有時(shí)候,眼力不是很好,這時(shí)候,人們開始打起了新主意。新來打水的人,他們看到有人排隊(duì)打水的時(shí)候,他們不會(huì)那么乖巧的就排到最后面去排隊(duì),反之,他們會(huì)看看現(xiàn)在有沒有人正在打水,如果有人在打水,沒輒了,只好排到隊(duì)列最后面,但如果這時(shí)候前面打水的人剛剛打完水,正在交接中,排在隊(duì)頭的人還沒有完成交接工作,這時(shí)候,新來的人可以嘗試搶打水權(quán),如果搶到了,呵呵,其他人也只能睜一只眼閉一只眼,因?yàn)榇蠹叶寄J(rèn)這個(gè)規(guī)則了。這就是所謂的非公平鎖模型。新來的人不一定總得乖乖排隊(duì),這也就造成了原來隊(duì)列中排隊(duì)的人可能要等很久很久。
java可重入鎖-ReentrantLock實(shí)現(xiàn)細(xì)節(jié)
ReentrantLock支持兩種獲取鎖的方式,一種是公平模型,一種是非公平模型。在繼續(xù)之前,咱們先把故事元素轉(zhuǎn)換為程序元素。
咱們先來說說公平鎖模型:
初始化時(shí), state=0,表示無人搶占了打水權(quán)。這時(shí)候,村民A來打水(A線程請(qǐng)求鎖),占了打水權(quán),把state+1,如下所示:
線程A取得了鎖,把 state原子性+1,這時(shí)候state被改為1,A線程繼續(xù)執(zhí)行其他任務(wù),然后來了村民B也想打水(線程B請(qǐng)求鎖),線程B無法獲取鎖,生成節(jié)點(diǎn)進(jìn)行排隊(duì),如下圖所示:
初始化的時(shí)候,會(huì)生成一個(gè)空的頭節(jié)點(diǎn),然后才是B線程節(jié)點(diǎn),這時(shí)候,如果線程A又請(qǐng)求鎖,是否需要排隊(duì)?答案當(dāng)然是否定的,否則就直接死鎖了。當(dāng)A再次請(qǐng)求鎖,就相當(dāng)于是打水期間,同一家人也來打水了,是有特權(quán)的,這時(shí)候的狀態(tài)如下圖所示:
到了這里,相信大家應(yīng)該明白了什么是可重入鎖了吧。就是一個(gè)線程在獲取了鎖之后,再次去獲取了同一個(gè)鎖,這時(shí)候僅僅是把狀態(tài)值進(jìn)行累加。如果線程A釋放了一次鎖,就成這樣了:
僅僅是把狀態(tài)值減了,只有線程A把此鎖全部釋放了,狀態(tài)值減到0了,其他線程才有機(jī)會(huì)獲取鎖。當(dāng)A把鎖完全釋放后,state恢復(fù)為0,然后會(huì)通知隊(duì)列喚醒B線程節(jié)點(diǎn),使B可以再次競爭鎖。當(dāng)然,如果B線程后面還有C線程,C線程繼續(xù)休眠,除非B執(zhí)行完了,通知了C線程。注意,當(dāng)一個(gè)線程節(jié)點(diǎn)被喚醒然后取得了鎖,對(duì)應(yīng)節(jié)點(diǎn)會(huì)從隊(duì)列中刪除。
非公平鎖模型
如果你已經(jīng)明白了前面講的公平鎖模型,那么非公平鎖模型也就非常容易理解了。當(dāng)線程A執(zhí)行完之后,要喚醒線程B是需要時(shí)間的,而且線程B醒來后還要再次競爭鎖,所以如果在切換過程當(dāng)中,來了一個(gè)線程C,那么線程C是有可能獲取到鎖的,如果C獲取到了鎖,B就只能繼續(xù)乖乖休眠了。這里就不再畫圖說明了。
其它知識(shí)點(diǎn)
java5中添加了一個(gè)并發(fā)包, java.util.concurrent,里面提供了各種并發(fā)的工具類,通過此工具包,可以在java當(dāng)中實(shí)現(xiàn)功能非常強(qiáng)大的多線程并發(fā)操作。對(duì)于每個(gè)java攻城獅,我覺得非常有必要了解這個(gè)包的功能。雖然做不到一步到位,但慢慢虛心學(xué)習(xí),沉下心來,總能慢慢領(lǐng)悟到j(luò)ava多線程編程的精華。
結(jié)束語
可重入鎖的實(shí)現(xiàn)會(huì)涉及到CAS,AQS,java內(nèi)存可見性(volatile)等知識(shí),為了避免大家直接被代碼搞暈,故而想以最簡單的方式把可重入鎖進(jìn)行抽象,講明白其中的實(shí)現(xiàn)原理,這樣看起源碼也有個(gè)借鑒的思路,希望本篇能夠幫助到你們。
---------------------
作者:那個(gè)天真的人
來源:CSDN
原文:https://blog.csdn.net/yanyan19880509/article/details/52345422
版權(quán)聲明:本文為博主原創(chuàng)文章,轉(zhuǎn)載請(qǐng)附上博文鏈接!
總結(jié)
以上是生活随笔為你收集整理的java中的账户冻结原理_java可重入锁(ReentrantLock)的实现原理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 折弯弹性计算公式_冲压模具:影响回弹因素
- 下一篇: java 实现打印条形码_条码打印软件中