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

