一個(gè)小例子幫助理解(我們常用的synchronized也是可重入鎖)
話說從前有一個(gè)村子蝎宇,在這個(gè)村子中有一口水井,家家戶戶都需要到這口井里打水喝襟齿。由于井水有限铸本,大家只能依次打水。為了實(shí)現(xiàn)家家有水喝体斩,戶戶有水用的目標(biāo)梭稚,村長(zhǎng)絞盡腦汁,最終想出了一個(gè)比較合理的方案絮吵。
首先弧烤,在水井邊上安排一個(gè)看井人,負(fù)責(zé)維持秩序蹬敲。
然后暇昂,打水時(shí),以家庭為單位伴嗡,哪個(gè)家庭任何人先到井邊急波,就可以先打水,而且如果一個(gè)家庭占到了打水權(quán)瘪校,其家人這時(shí)候過來打水不用排隊(duì)澄暮。而那些沒有搶占到打水權(quán)的人,一個(gè)一個(gè)挨著在井邊排成一隊(duì)阱扬,先到的排在前面赏寇。
最后,打水的人打完水以后就告訴看井人价认,看井人就讓等待的隊(duì)伍中的最前面一個(gè)去打水嗅定。
這樣一來,大家都能打到水用踩,也保證了相對(duì)的公平渠退。這就是公平鎖的基本思路忙迁。
隨著時(shí)間的推移,村民發(fā)現(xiàn)每次去打水的時(shí)候都需要排隊(duì)碎乃,想著每次排隊(duì)都浪費(fèi)時(shí)間姊扔,于是就把水桶放在井邊代替,自己則溜回家去了梅誓。這樣一搞恰梢,可把看井人累壞,經(jīng)常往村民家里跑梗掰,讓他們來打水嵌言。于是聰明的看井人想出了一個(gè)對(duì)策,如果有人打完水后及穗,剛好又有其它人來打水摧茴,就直接讓這個(gè)新來的人上去打水,不用到隊(duì)伍末尾去排隊(duì)等候埂陆。
這種方式雖然看上去不公平苛白,但是他節(jié)省了資源,提高了打水的性能焚虱,這就是非公平鎖的基本思路购裙。
打水的小故事在java中的應(yīng)用
Java中可重入鎖-ReentrantLock基本上就是按照上面的思路來實(shí)現(xiàn)的,我們來對(duì)給他們做一個(gè)簡(jiǎn)單的對(duì)比鹃栽。
一次只有一個(gè)人能打水 鎖需要保證多線程的同步缓窜。
必須嚴(yán)格按照排隊(duì)順序打水 ReentrantLock提供的公平鎖功能。
來得早不如來得巧 ReentrantLock提供的非公平鎖功能谍咆。
有家人正在打水的時(shí)候就不需要排隊(duì) ReentrantLock的可重入特性禾锤。
那么可重入鎖又是怎樣實(shí)現(xiàn)上面那些特性的呢?
java可重入鎖-ReentrantLock實(shí)現(xiàn)細(xì)節(jié)
首先我們從上面的故事入手摹察,看看ReentrantLock中的各個(gè)角色都是怎么樣的恩掷。
打水權(quán) volatile int state
打水者 線程、Thread
打水隊(duì)伍 雙向鏈表Node
獲取鎖的時(shí)候供嚎,公平鎖的整個(gè)工作流程就如下圖所示:
可重入公平鎖獲取流程
在獲取鎖的時(shí)候黄娘,如果當(dāng)前線程之前已經(jīng)獲取到了鎖,就會(huì)把state加1克滴,在釋放鎖的時(shí)候會(huì)先減1逼争,這樣就保證了同一個(gè)鎖可以被同一個(gè)線程獲取多次,而不會(huì)出現(xiàn)死鎖的情況劝赔。這就是ReentrantLock的可重入性誓焦。
對(duì)于非公平鎖而言,調(diào)用lock方法后着帽,會(huì)先嘗試搶占鎖杂伟,在各種判斷的時(shí)候會(huì)先忽略等待隊(duì)列移层,如果鎖可用,就會(huì)直接搶占使用赫粥。
釋放鎖的時(shí)候观话,整個(gè)工作流程如下圖:
可重入鎖釋放過程
本文為轉(zhuǎn)載:https://baijiahao.baidu.com/s?id=1594800969528243663&wfr=spider&for=pc
參考:https://blog.csdn.net/yanyan19880509/article/details/52345422