摘要:為什么叫重入鎖呢,我們把它拆開來看就明了了。釋放鎖,每次鎖持有者數(shù)量遞減,直到為止。
相信大家在工作或者面試過程中經(jīng)常聽到重入鎖這個(gè)概念,或者與關(guān)鍵字 synchrozied 的對(duì)比,棧長面試了這么多人,80%的面試者都沒有答對(duì)或沒有答到點(diǎn)上,或者把雙重效驗(yàn)鎖搞混了,哭笑不得。。
那么你對(duì)重入鎖了解有多少呢?今天,棧長幫大家撕開重入鎖的面紗,來見識(shí)下重入鎖的真實(shí)容顏。。
什么是重入鎖java.util.concurrent.locks.ReentrantLock
這個(gè)是 JDK @since 1.5 添加的一種顆粒度更小的鎖,它完全可以替代 synchronized 關(guān)鍵字來實(shí)現(xiàn)它的所有功能,而且 ReentrantLock 鎖的靈活度要遠(yuǎn)遠(yuǎn)大于 synchronized 關(guān)鍵字。
從類結(jié)構(gòu)圖看出,ReentrantLock 實(shí)現(xiàn)了 Lock 接口,ReentrantLock 只是 Lock 接口的一個(gè)實(shí)現(xiàn)而已。
java.util.concurrent.locks.Lock
它們都是 java.util.concurrent 包里面的內(nèi)容(俗稱 JUC、并發(fā)包),也都是 JDK 1.5 開始加入的。
為什么叫重入鎖呢?ReentrantLock,我們把它拆開來看就明了了。
Re-Entrant-Lock:即表示可重新反復(fù)進(jìn)入的鎖,但僅限于當(dāng)前線程;
public void m() { lock.lock(); lock.lock(); try { // ... method body } finally { lock.unlock() lock.unlock() } }
如示例代碼所示,當(dāng)前線程可以反復(fù)加鎖,但也需要釋放同樣加鎖次數(shù)的鎖,即重入了多少次,就要釋放多少次,不然也會(huì)導(dǎo)入鎖不被釋放。
試想一下,如果不設(shè)計(jì)成可重入鎖,那自己如果反復(fù)給自己加鎖,不是會(huì)把自己加死鎖了嗎?所以,到現(xiàn)在,重入鎖的概念大概應(yīng)該清楚了吧?
重入鎖最重要的幾個(gè)方法這幾個(gè)方法都是 Lock 接口中定義的:
1)lock()
獲取鎖,有以下三種情況:
鎖空閑:直接獲取鎖并返回,同時(shí)設(shè)置鎖持有者數(shù)量為:1;
當(dāng)前線程持有鎖:直接獲取鎖并返回,同時(shí)鎖持有者數(shù)量遞增1;
其他線程持有鎖:當(dāng)前線程會(huì)休眠等待,直至獲取鎖為止;
2)lockInterruptibly()
獲取鎖,邏輯和 lock() 方法一樣,但這個(gè)方法在獲取鎖過程中能響應(yīng)中斷。
3)tryLock()
從關(guān)鍵字字面理解,這是在嘗試獲取鎖,獲取成功返回:true,獲取失敗返回:false, 這個(gè)方法不會(huì)等待,有以下三種情況:
鎖空閑:直接獲取鎖并返回:true,同時(shí)設(shè)置鎖持有者數(shù)量為:1;
當(dāng)前線程持有鎖:直接獲取鎖并返回:true,同時(shí)鎖持有者數(shù)量遞增1;
其他線程持有鎖:獲取鎖失敗,返回:false;
4)tryLock(long timeout, TimeUnit unit)
邏輯和 tryLock() 差不多,只是這個(gè)方法是帶時(shí)間的。
5)unlock()
釋放鎖,每次鎖持有者數(shù)量遞減 1,直到 0 為止。所以,現(xiàn)在知道為什么 lock 多少次,就要對(duì)應(yīng) unlock 多少次了吧。
6)newCondition
返回一個(gè)這個(gè)鎖的 Condition 實(shí)例,可以實(shí)現(xiàn) synchronized 關(guān)鍵字類似 wait/ notify 實(shí)現(xiàn)多線程通信的功能,不過這個(gè)比 wait/ notify 要更靈活,更強(qiáng)大!
重入鎖大概的用法class X { private final ReentrantLock lock = new ReentrantLock(); // ... public void m() { lock.lock(); // block until condition holds try { // ... method body } finally { lock.unlock() } } }}
看見沒有,加鎖和釋放鎖都在方法里面進(jìn)行,可以自由控制,比 synchronized 更靈活,更方便。但要注意的是,釋放鎖操作必須在 finally 里面,不然如果出現(xiàn)異常導(dǎo)致鎖不能被正常釋放,進(jìn)而會(huì)卡死后續(xù)所有訪問該鎖的線程。
synchronized 是重入鎖嗎?那么問題來了,synchronized 是重入鎖嗎?
你可能會(huì)說不是,因?yàn)?ReentrantLock 既然是重入鎖,根據(jù)推理,相反,那 synchronized 肯定就不是重入鎖,那你就錯(cuò)了。
答案是:yes,為什么?看下面的例子:
public synchronized void operation(){ add(); } public synchronized void add(){ }
operation 方法調(diào)用了 add 方法,兩個(gè)方法都是用 synchronized 修飾的,add() 方法可以成功獲取當(dāng)前線程 operation() 方法已經(jīng)獲取到的鎖,說明 synchronized 就是可重入鎖。
面試常問的Synchronized的幾種用法推薦看下這篇文章:Synchronized 有幾種用法?。
總結(jié)今天,重入鎖就大概寫到這里了,其實(shí)重入鎖就是一種顆粒度更小的鎖,控制更方便,更強(qiáng)大,棧長只是簡單介紹一下重入鎖的基本概念及用法,但遠(yuǎn)不止這么簡單,還有很多,一篇也難也詳盡,夠?qū)懞枚嗥恕?/p>
大家也可以關(guān)注微信公眾號(hào):Java技術(shù)棧,棧長將繼續(xù)分享更多重入鎖的高級(jí)的概念及工作中的實(shí)戰(zhàn)用法,請(qǐng)關(guān)注后續(xù)文章,或者在公眾號(hào)后臺(tái)回復(fù):多線程,棧長已經(jīng)整理好了許多 Java 多線程系列文章,都是接地氣干貨。
覺得有用,轉(zhuǎn)發(fā)分享下朋友圈給更多的人看吧,另外,給個(gè)好看,謝謝老板~
關(guān)注Java技術(shù)棧微信公眾號(hào),棧長將繼續(xù)分享 Java 干貨教程,公眾號(hào)第一時(shí)間推送,持續(xù)關(guān)注。在公眾號(hào)后臺(tái)回復(fù):java,獲取棧長整理的更多的 Java 教程,都是實(shí)戰(zhàn)干貨,以下僅為部分預(yù)覽。
你真的搞懂 transient 關(guān)鍵字了嗎?
面試常考:Synchronized 有幾種用法?
Java 11 已發(fā)布,String 還能這樣玩!
Java 中的 String 真的是不可變嗎?
sleep( ) 和 wait( ) 的這 5 個(gè)區(qū)別
……
本文原創(chuàng)首發(fā)于微信公眾號(hào):Java技術(shù)棧(id:javastack),轉(zhuǎn)載請(qǐng)?jiān)瓨颖A舯拘畔ⅰ?/p>
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/75024.html
摘要:所謂的重入,就是當(dāng)本線程想再次獲得鎖,不需要重新申請(qǐng),它本身就已經(jīng)鎖了,即重入該鎖。如果不為,則表示有線程已經(jīng)占有了??偨Y(jié)回顧下要點(diǎn)是一個(gè)可重入的鎖被當(dāng)前占用的線程重入。 上一章《AQS源碼閱讀》講了AQS框架,這次講講它的應(yīng)用類(注意不是子類實(shí)現(xiàn),待會(huì)細(xì)講)。ReentrantLock,顧名思義重入鎖,但什么是重入,這個(gè)鎖到底是怎樣的,我們來看看類的注解說明showImg(http:...
摘要:二什么是重入鎖可重入鎖,顧名思義,支持重新進(jìn)入的鎖,其表示該鎖能支持一個(gè)線程對(duì)資源的重復(fù)加鎖。將由最近成功獲得鎖,并且還沒有釋放該鎖的線程所擁有??梢允褂煤头椒▉頇z查此情況是否發(fā)生。 一、寫在前面 前幾篇我們具體的聊了AQS原理以及底層源碼的實(shí)現(xiàn),具體參見 《J.U.C|一文搞懂AQS》《J.U.C|同步隊(duì)列(CLH)》《J.U.C|AQS獨(dú)占式源碼分析》《J.U.C|AQS共享式源...
摘要:本文旨在對(duì)鎖相關(guān)源碼本文中的源碼來自使用場景進(jìn)行舉例,為讀者介紹主流鎖的知識(shí)點(diǎn),以及不同的鎖的適用場景。中,關(guān)鍵字和的實(shí)現(xiàn)類都是悲觀鎖。自適應(yīng)意味著自旋的時(shí)間次數(shù)不再固定,而是由前一次在同一個(gè)鎖上的自旋時(shí)間及鎖的擁有者的狀態(tài)來決定。 前言 Java提供了種類豐富的鎖,每種鎖因其特性的不同,在適當(dāng)?shù)膱鼍跋履軌蛘宫F(xiàn)出非常高的效率。本文旨在對(duì)鎖相關(guān)源碼(本文中的源碼來自JDK 8)、使用場景...
摘要:自己實(shí)現(xiàn)在自己實(shí)現(xiàn)之前先搞清楚阻塞隊(duì)列的幾個(gè)特點(diǎn)基本隊(duì)列特性先進(jìn)先出。消費(fèi)隊(duì)列空時(shí)會(huì)阻塞直到寫入線程寫入了隊(duì)列數(shù)據(jù)后喚醒消費(fèi)線程。最終的隊(duì)列大小為,可見線程也是安全的。 showImg(https://segmentfault.com/img/remote/1460000018811340); 前言 較長一段時(shí)間以來我都發(fā)現(xiàn)不少開發(fā)者對(duì) jdk 中的 J.U.C(java.util.c...
摘要:所以通過設(shè)置一個(gè)適中的拉取注冊表以及發(fā)送心跳的頻率,保證大規(guī)模系統(tǒng)里對(duì)的請(qǐng)求壓力不會(huì)太大。在注冊表發(fā)生變更的時(shí)候會(huì)在內(nèi)存中更新變更的注冊表數(shù)據(jù),同時(shí)過期掉。上述就是架構(gòu)中,作為微服務(wù)注冊中心可以承載大規(guī)模系統(tǒng)每天千萬級(jí)訪問量的原理。 歡迎關(guān)注微信公眾號(hào):石杉的架構(gòu)筆記 周一至周五早8點(diǎn)!精品技術(shù)文章準(zhǔn)時(shí)送上?。?往期文章1.拜托!面試請(qǐng)不要再問我Spring Cloud底層原理! 目...
閱讀 2100·2021-11-23 09:51
閱讀 1302·2019-08-30 15:55
閱讀 1673·2019-08-30 15:44
閱讀 812·2019-08-30 14:11
閱讀 1201·2019-08-30 14:10
閱讀 976·2019-08-30 13:52
閱讀 2699·2019-08-30 12:50
閱讀 681·2019-08-29 15:04