最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

深入理解java內(nèi)置鎖(synchronized)和顯式鎖(ReentrantLock)

 更新時(shí)間:2017年11月26日 07:12:26   投稿:laozhang  
這篇文章主要介紹了Java多線程之內(nèi)置鎖(synchronized)和顯式鎖(ReentrantLock)的深入理解新的和用法,具有一定參考價(jià)值,需要的朋友可以了解下。

synchronized 和 Reentrantlock

多線程編程中,當(dāng)代碼需要同步時(shí)我們會(huì)用到鎖。Java為我們提供了內(nèi)置鎖(synchronized)和顯式鎖(ReentrantLock)兩種同步方式。顯式鎖是JDK1.5引入的,這兩種鎖有什么異同呢?是僅僅增加了一種選擇還是另有其因?本文為您一探究竟。

// synchronized關(guān)鍵字用法示例
public synchronized void add(int t){// 同步方法
  this.v += t;
}

public static synchronized void sub(int t){// 同步靜態(tài)方法
  value -= t;
}
public int decrementAndGet(){
  synchronized(obj){// 同步代碼塊
    return --v;
  }
}

這就是內(nèi)置鎖的全部用法,你已經(jīng)學(xué)會(huì)了。

內(nèi)置鎖使用起來非常方便,不需要顯式的獲取和釋放,任何一個(gè)對(duì)象都能作為一把內(nèi)置鎖。使用內(nèi)置鎖能夠解決大部分的同步場(chǎng)景。“任何一個(gè)對(duì)象都能作為一把內(nèi)置鎖”也意味著出現(xiàn)synchronized關(guān)鍵字的地方,都有一個(gè)對(duì)象與之關(guān)聯(lián),具體說來:

當(dāng)synchronized作用于普通方法是,鎖對(duì)象是this;

當(dāng)synchronized作用于靜態(tài)方法是,鎖對(duì)象是當(dāng)前類的Class對(duì)象;

當(dāng)synchronized作用于代碼塊時(shí),鎖對(duì)象是synchronized(obj)中的這個(gè)obj。

顯式鎖

內(nèi)置鎖這么好用,為什么還需多出一個(gè)顯式鎖呢?因?yàn)橛行┦虑閮?nèi)置鎖是做不了的,比如:

我們想給鎖加個(gè)等待時(shí)間超時(shí)時(shí)間,超時(shí)還未獲得鎖就放棄,不至于無(wú)限等下去;

我們想以可中斷的方式獲取鎖,這樣外部線程給我們發(fā)一個(gè)中斷信號(hào)就能喚起等待鎖的線程;

我們想為鎖維持多個(gè)等待隊(duì)列,比如一個(gè)生產(chǎn)者隊(duì)列,一個(gè)消費(fèi)者隊(duì)列,一邊提高鎖的效率。

顯式鎖(ReentrantLock)正式為了解決這些靈活需求而生。ReentrantLock的字面意思是可重入鎖,可重入的意思是線程可以同時(shí)多次請(qǐng)求同一把鎖,而不會(huì)自己導(dǎo)致自己死鎖。下面是內(nèi)置鎖和顯式鎖的區(qū)別:

可定時(shí):RenentrantLock.tryLock(long timeout, TimeUnit unit)提供了一種以定時(shí)結(jié)束等待的方式,如果線程在指定的時(shí)間內(nèi)沒有獲得鎖,該方法就會(huì)返回false并結(jié)束線程等待。

可中斷:你一定見過InterruptedException,很多跟多線程相關(guān)的方法會(huì)拋出該異常,這個(gè)異常并不是一個(gè)缺陷導(dǎo)致的負(fù)擔(dān),而是一種必須,或者說是一件好事??芍袛嘈越o我們提供了一種讓線程提前結(jié)束的方式(而不是非得等到線程執(zhí)行結(jié)束),這對(duì)于要取消耗時(shí)的任務(wù)非常有用。對(duì)于內(nèi)置鎖,線程拿不到內(nèi)置鎖就會(huì)一直等待,除了獲取鎖沒有其他辦法能夠讓其結(jié)束等待。RenentrantLock.lockInterruptibly()給我們提供了一種以中斷結(jié)束等待的方式。

條件隊(duì)列(condition queue):線程在獲取鎖之后,可能會(huì)由于等待某個(gè)條件發(fā)生而進(jìn)入等待狀態(tài)(內(nèi)置鎖通過Object.wait()方法,顯式鎖通過Condition.await()方法),進(jìn)入等待狀態(tài)的線程會(huì)掛起并自動(dòng)釋放鎖,這些線程會(huì)被放入到條件隊(duì)列當(dāng)中。synchronized對(duì)應(yīng)的只有一個(gè)條件隊(duì)列,而ReentrantLock可以有多個(gè)條件隊(duì)列,多個(gè)隊(duì)列有什么好處呢?請(qǐng)往下看。

條件謂詞:線程在獲取鎖之后,有時(shí)候還需要等待某個(gè)條件滿足才能做事情,比如生產(chǎn)者需要等到“緩存不滿”才能往隊(duì)列里放入消息,而消費(fèi)者需要等到“緩存非空”才能從隊(duì)列里取出消息。這些條件被稱作條件謂詞,線程需要先獲取鎖,然后判斷條件謂詞是否滿足,如果不滿足就不往下執(zhí)行,相應(yīng)的線程就會(huì)放棄執(zhí)行權(quán)并自動(dòng)釋放鎖。使用同一把鎖的不同的線程可能有不同的條件謂詞,如果只有一個(gè)條件隊(duì)列,當(dāng)某個(gè)條件謂詞滿足時(shí)就無(wú)法判斷該喚醒條件隊(duì)列里的哪一個(gè)線程;但是如果每個(gè)條件謂詞都有一個(gè)單獨(dú)的條件隊(duì)列,當(dāng)某個(gè)條件滿足時(shí)我們就知道應(yīng)該喚醒對(duì)應(yīng)隊(duì)列上的線程(內(nèi)置鎖通過Object.notify()或者Object.notifyAll()方法喚醒,顯式鎖通過Condition.signal()或者Condition.signalAll()方法喚醒)。這就是多個(gè)條件隊(duì)列的好處。

使用內(nèi)置鎖時(shí),對(duì)象本身既是一把鎖又是一個(gè)條件隊(duì)列;使用顯式鎖時(shí),RenentrantLock的對(duì)象是鎖,條件隊(duì)列通過RenentrantLock.newCondition()方法獲取,多次調(diào)用該方法可以得到多個(gè)條件隊(duì)列。

一個(gè)使用顯式鎖的典型示例如下:

// 顯式鎖的使用示例
ReentrantLock lock = new ReentrantLock();

// 獲取鎖,這是跟synchronized關(guān)鍵字對(duì)應(yīng)的用法。
lock.lock();
try{
  // your code
}finally{
  lock.unlock();
}

// 可定時(shí),超過指定時(shí)間為得到鎖就放棄
try {
  lock.tryLock(10, TimeUnit.SECONDS);
  try {
    // your code
  }finally {
    lock.unlock();
  }
} catch (InterruptedException e1) {
  // exception handling
}

// 可中斷,等待獲取鎖的過程中線程線程可被中斷
try {
  lock.lockInterruptibly();
  try {
    // your code
  }finally {
    lock.unlock();
  }
} catch (InterruptedException e) {
  // exception handling
}

// 多個(gè)等待隊(duì)列,具體參考[ArrayBlockingQueue](https://github.com/CarpenterLee/JCRecipes/blob/master/markdown/ArrayBlockingQueue.md)
/** Condition for waiting takes */
private final Condition notEmpty = lock.newCondition();
/** Condition for waiting puts */
private final Condition notFull = lock.newCondition();

注意,上述代碼將unlock()放在finally塊里,這么做是必需的。顯式鎖不像內(nèi)置鎖那樣會(huì)自動(dòng)釋放,使用顯式鎖一定要在finally塊中手動(dòng)釋放,如果獲取鎖后由于異常的原因沒有釋放鎖,那么這把鎖將永遠(yuǎn)得不到釋放!將unlock()放在finally塊中,保證無(wú)論發(fā)生什么都能夠正常釋放。

結(jié)論

內(nèi)置鎖能夠解決大部分需要同步的場(chǎng)景,只有在需要額外靈活性是才需要考慮顯式鎖,比如可定時(shí)、可中斷、多等待隊(duì)列等特性。

顯式鎖雖然靈活,但是需要顯式的申請(qǐng)和釋放,并且釋放一定要放到finally塊中,否則可能會(huì)因?yàn)楫惓?dǎo)致鎖永遠(yuǎn)無(wú)法釋放!這是顯式鎖最明顯的缺點(diǎn)。

綜上,當(dāng)需要同步時(shí)請(qǐng)優(yōu)先考慮更安全的更易用的隱式鎖。

相關(guān)文章

  • Java?BeanUtils?類作用、語(yǔ)法與示例詳解

    Java?BeanUtils?類作用、語(yǔ)法與示例詳解

    BeanUtils是Apache?Commons和Spring?Framework提供的工具類,主要用于簡(jiǎn)化JavaBean的操作,接下來通過本文給大家介紹Java?BeanUtils?類作用、語(yǔ)法與示例詳解,感興趣的朋友跟隨小編一起看看吧
    2025-08-08
  • Java框架MyBatis接口編程過程解析

    Java框架MyBatis接口編程過程解析

    這篇文章主要介紹了Java框架MyBatis接口編程過程解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-02-02
  • java反射耗時(shí)測(cè)試案例解析

    java反射耗時(shí)測(cè)試案例解析

    這篇文章主要介紹了java反射耗時(shí)測(cè)試案例解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-10-10
  • SpringBoot?全局線程池配置及應(yīng)用小結(jié)

    SpringBoot?全局線程池配置及應(yīng)用小結(jié)

    為了提高應(yīng)用程序的性能和響應(yīng)速度,線程池是一個(gè)非常重要的工具,本文主要介紹了Spring?Boot?全局線程池配置及應(yīng)用,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-05-05
  • IDEA中WEB項(xiàng)目結(jié)構(gòu)和Artifacts設(shè)置方式

    IDEA中WEB項(xiàng)目結(jié)構(gòu)和Artifacts設(shè)置方式

    本文詳細(xì)介紹了Maven項(xiàng)目結(jié)構(gòu)設(shè)置及正確Artifacts配置方法,包括IDEA項(xiàng)目結(jié)構(gòu)設(shè)置、文件夾類型配置及打包發(fā)布步驟,幫助開發(fā)者實(shí)現(xiàn)高效項(xiàng)目部署
    2026-06-06
  • Java Poi 在Excel中輸出特殊符號(hào)的實(shí)現(xiàn)方法

    Java Poi 在Excel中輸出特殊符號(hào)的實(shí)現(xiàn)方法

    這篇文章主要介紹了Java Poi 在Excel中輸出特殊符號(hào)的實(shí)現(xiàn)方法,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-07-07
  • Spring注解實(shí)現(xiàn)自動(dòng)裝配過程解析

    Spring注解實(shí)現(xiàn)自動(dòng)裝配過程解析

    這篇文章主要介紹了Spring注解實(shí)現(xiàn)自動(dòng)裝配過程解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-03-03
  • jmeter基礎(chǔ)邏輯控制器之if控制器的使用

    jmeter基礎(chǔ)邏輯控制器之if控制器的使用

    在實(shí)際工作中,當(dāng)使用JMeter做性能腳本或者接口腳本時(shí),當(dāng)遇到需要對(duì)不同的條件做不同的操作時(shí),我們可以使用JMeter中if控制器來實(shí)現(xiàn),本文就詳細(xì)的介紹一下如何使用
    2021-11-11
  • Java技能點(diǎn)之SimpleDateFormat進(jìn)行日期格式化問題

    Java技能點(diǎn)之SimpleDateFormat進(jìn)行日期格式化問題

    這篇文章主要介紹了Java技能點(diǎn)之SimpleDateFormat進(jìn)行日期格式化問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-04-04
  • 基于 SASL/SCRAM 讓 Kafka 實(shí)現(xiàn)動(dòng)態(tài)授權(quán)認(rèn)證的方法

    基于 SASL/SCRAM 讓 Kafka 實(shí)現(xiàn)動(dòng)態(tài)授權(quán)認(rèn)證的方法

    在大數(shù)據(jù)處理和分析中?Apache Kafka?已經(jīng)成為了一個(gè)核心組件,本文將從零開始部署?ZooKeeper?和?Kafka?并通過配置?SASL/SCRAM?和?ACL(訪問控制列表)來增強(qiáng)?Kafka?的安全性,需要的朋友可以參考下
    2024-07-07

最新評(píng)論

安化县| 南京市| 巴青县| 德阳市| 满洲里市| 吴旗县| 彰武县| 扬州市| 长宁县| 博乐市| 大同县| 班戈县| 织金县| 菏泽市| 凌云县| 雅江县| 汕尾市| 青阳县| 锡林浩特市| 墨江| 新津县| 东平县| 峨边| 雷波县| 锡林浩特市| 泰宁县| 千阳县| 苏州市| 油尖旺区| 无极县| 西华县| 永登县| 陆河县| 噶尔县| 彭泽县| 东方市| 崇明县| 南部县| 曲周县| 天镇县| 祁门县|