Java中的鎖ReentrantLock詳解
一、 ReentrantLock使用
1.1 簡(jiǎn)單使用
public class LockTest { // 新建鎖 Lock lock = new ReentrantLock(); public static void main(String[] args) { // 測(cè)試 LockTest test = new LockTest(); test.te(); } public void te(){ try { // 獲取鎖 lock.lock(); System.out.println("獲取到鎖執(zhí)行代碼!"); } catch (Exception e) { e.printStackTrace(); } finally { // 一定注意 在finally中釋放鎖 lock.unlock(); } } }
1.2 tryLock
Lock比synchronized還是多一些功能的,比如可以設(shè)置規(guī)定時(shí)間內(nèi)獲取不到鎖就返回,不一直阻塞。
一個(gè)不合時(shí)宜的例子就是:
synchronize就是一個(gè)舔狗,一直舔 直到天荒地老
lock 的 tryLock 就像是一個(gè)渣男,輕輕嘗試一下,不合適抓緊下一個(gè)
public class LockTest02 { // 新建鎖 Lock lock = new ReentrantLock(); public static void main(String[] args) { // 測(cè)試 LockTest02 test = new LockTest02(); new Thread(()->test.te()).start(); // test::teTryLock lambda寫(xiě)法 new Thread(test::teTryLock).start(); } private void teTryLock() { boolean res = false; try { // 嘗試獲取 5秒鐘獲取不到就結(jié)束 res = lock.tryLock(5,TimeUnit.SECONDS); if (res) { System.out.println("teTryLock獲取到鎖了,執(zhí)行獲取到鎖的代碼"); } else{ System.out.println("teTryLock沒(méi)有獲取到鎖 執(zhí)行沒(méi)有獲取到鎖的代碼"); } } catch (Exception e) { e.printStackTrace(); } finally { // 如果獲取到鎖了 再釋放 if (res) { lock.unlock(); } } } public void te(){ try { // 獲取鎖 lock.lock(); System.out.println("te獲取到鎖執(zhí)行代碼!"); Thread.sleep(10000); } catch (Exception e) { e.printStackTrace(); } finally { // 一定注意 在finally中釋放鎖 lock.unlock(); System.out.println("te釋放鎖!"); } } }
輸出結(jié)果:
te獲取到鎖執(zhí)行代碼!
teTryLock沒(méi)有獲取到鎖 執(zhí)行沒(méi)有獲取到鎖的代碼
te釋放鎖!
1.3 lockInterruptibly
synchronized 如果開(kāi)始等待是不能結(jié)束的
但是Lock使用lockInterruptibly 可以被中斷 在異常捕獲里捕獲異常 然后做一些后置處理
public class LockTest03 { // 新建鎖 Lock lock = new ReentrantLock(); public static void main(String[] args) throws InterruptedException { // 測(cè)試 LockTest03 test = new LockTest03(); new Thread(test::te).start(); Thread thread = new Thread(test::teLockInterruptibly); thread.start(); Thread.sleep(3000); thread.interrupt(); } private void teLockInterruptibly() { boolean res = true; try { // 嘗試獲取 5秒鐘獲取不到就結(jié)束 lock.lockInterruptibly(); System.out.println("獲取到鎖··"); } catch (InterruptedException e) { //沒(méi)有正常獲取鎖 被Interrupt了 res = false; System.out.println("InterruptedException:被打斷了 做一些其他處理"); } finally { // 如果沒(méi)被打斷 是正常獲取鎖的(理論上是,也可能有其他異常) if(res) { lock.unlock(); } } } public void te(){ try { // 獲取鎖 lock.lock(); System.out.println("te獲取到鎖執(zhí)行代碼!"); // te 方法睡死過(guò)去了 Thread.sleep(10000000); } catch (Exception e) { e.printStackTrace(); } finally { // 一定注意 在finally中釋放鎖 lock.unlock(); System.out.println("te釋放鎖!"); } } }
1.4 公平鎖
synchronized是非公平鎖 后來(lái)的也可能會(huì)先獲取到鎖
Lock鎖默認(rèn)也是非公平鎖
非公平鎖是什么樣的?
用不要臉的小強(qiáng)來(lái)做比喻,假設(shè)有10個(gè)人在排隊(duì)買餅,小強(qiáng)這時(shí)候也來(lái)買餅了,不要臉的他直接跑第一個(gè)位置,這時(shí)候如果正有人在選餅,那他就灰溜溜的走了,如果上一個(gè)人剛好買完,下一個(gè)人還沒(méi)有開(kāi)始選,那不要臉的小強(qiáng)就會(huì)趁著這個(gè)間隙直接跟老板選餅. 這樣對(duì)于后邊排隊(duì)的是不公平的 所以稱為不公平鎖
在ReentrantLock的實(shí)現(xiàn)中,不要臉的小強(qiáng)會(huì)嘗試好幾次,最后都失敗的話他才會(huì)去隊(duì)尾排隊(duì)
Lock可以實(shí)現(xiàn)公平鎖:公平鎖就是lock的時(shí)候會(huì)先去排隊(duì)隊(duì)列里邊看看,有沒(méi)有人在排隊(duì),有的話站后邊去,可以看我寫(xiě)過(guò)的AQS ,用公平鎖做的舉例 講到了源碼層
注意:公平鎖不是完全公平,公平鎖只是會(huì)檢查隊(duì)列里有沒(méi)有人排隊(duì),如果沒(méi)有自己去申請(qǐng)鎖,如果有自己去排隊(duì),去檢查有沒(méi)有人排隊(duì)的時(shí)候可能會(huì)出現(xiàn)不公平(地鐵一個(gè)人一大步竄你前邊了),進(jìn)隊(duì)列的時(shí)候也可能會(huì)出現(xiàn)不公平(地鐵一個(gè)人一大步竄你前邊了)
Lock lock = new ReentrantLock(true); // true表示公平
到此這篇關(guān)于Java中的鎖ReentrantLock詳解的文章就介紹到這了,更多相關(guān)ReentrantLock詳解內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
基于springboot服務(wù)間Feign調(diào)用超時(shí)的解決方案
這篇文章主要介紹了基于springboot服務(wù)間Feign調(diào)用超時(shí)的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-07-07PowerJob的DatabaseMonitorAspect源碼流程
這篇文章主要為大家介紹了PowerJob的DatabaseMonitorAspect源碼流程解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2024-01-01Java實(shí)現(xiàn)帶GUI的氣泡詩(shī)詞效果
這篇文章主要為大家介紹了如何利用Java實(shí)現(xiàn)帶GUI的氣泡詩(shī)詞效果,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)Java有一定幫助,感興趣的可以了解一下2022-12-12如何基于java實(shí)現(xiàn)解壓ZIP TAR等文件
這篇文章主要介紹了如何基于java實(shí)現(xiàn)解壓ZIP TAR等文件,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-07-07Java高效提取PDF文件指定坐標(biāo)的文本內(nèi)容實(shí)戰(zhàn)代碼
在日常工作中,有時(shí)可能會(huì)需要從龐大的PDF文檔中提取其中所包含的文本內(nèi)容,下面這篇文章主要給大家介紹了關(guān)于如何利用Java高效提取PDF文件指定坐標(biāo)的文本內(nèi)容,需要的朋友可以參考下2024-01-01Java 中Comparable和Comparator區(qū)別比較
本文,先介紹Comparable 和Comparator兩個(gè)接口,以及它們的差異;接著,通過(guò)示例,對(duì)它們的使用方法進(jìn)行說(shuō)明2013-09-09springmvc學(xué)習(xí)筆記-返回json的日期格式問(wèn)題的解決方法
本篇文章主要介紹了springmvc學(xué)習(xí)筆記-返回json的日期格式問(wèn)題的解決方法,解決了日期格式的輸出,有興趣的可以了解一下。2017-01-01Mybatis中一對(duì)多(collection)和一對(duì)一(association)的組合查詢使用
這篇文章主要介紹了Mybatis中一對(duì)多(collection)和一對(duì)一(association)的組合查詢使用,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-12-12基于Java的Spring框架來(lái)操作FreeMarker模板的示例
這篇文章主要介紹了基于Java的Spring框架來(lái)操作FreeMarker模板的示例,講到了用于進(jìn)行web模板文件的插值操作等例子,需要的朋友可以參考下2016-03-03