亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

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

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

synchronized 和 Reentrantlock

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

// synchronized關鍵字用法示例
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)學會了。

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

當synchronized作用于普通方法是,鎖對象是this;

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

當synchronized作用于代碼塊時,鎖對象是synchronized(obj)中的這個obj。

顯式鎖

內(nèi)置鎖這么好用,為什么還需多出一個顯式鎖呢?因為有些事情內(nèi)置鎖是做不了的,比如:

我們想給鎖加個等待時間超時時間,超時還未獲得鎖就放棄,不至于無限等下去;

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

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

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

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

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

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

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

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

一個使用顯式鎖的典型示例如下:

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

// 獲取鎖,這是跟synchronized關鍵字對應的用法。
lock.lock();
try{
  // your code
}finally{
  lock.unlock();
}

// 可定時,超過指定時間為得到鎖就放棄
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
}

// 多個等待隊列,具體參考[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)置鎖那樣會自動釋放,使用顯式鎖一定要在finally塊中手動釋放,如果獲取鎖后由于異常的原因沒有釋放鎖,那么這把鎖將永遠得不到釋放!將unlock()放在finally塊中,保證無論發(fā)生什么都能夠正常釋放。

結論

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

顯式鎖雖然靈活,但是需要顯式的申請和釋放,并且釋放一定要放到finally塊中,否則可能會因為異常導致鎖永遠無法釋放!這是顯式鎖最明顯的缺點。

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

相關文章

  • Java中關于控制臺讀取數(shù)字或字符串的方法

    Java中關于控制臺讀取數(shù)字或字符串的方法

    下面小編就為大家?guī)硪黄狫ava中關于控制臺讀取數(shù)字或字符串的方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-10-10
  • 基于springboot實現(xiàn)一個簡單的aop實例

    基于springboot實現(xiàn)一個簡單的aop實例

    這篇文章主要介紹了基于springboot實現(xiàn)一個簡單的aop,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-11-11
  • Mybatis使用concat函數(shù)問題

    Mybatis使用concat函數(shù)問題

    這篇文章主要介紹了Mybatis使用concat函數(shù)問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • Java面試題沖刺第八天--Spring框架2

    Java面試題沖刺第八天--Spring框架2

    這篇文章主要為大家分享了最有價值的三道Spring框架面試題,涵蓋內(nèi)容全面,包括數(shù)據(jù)結構和算法相關的題目、經(jīng)典面試編程題等,感興趣的小伙伴們可以參考一下
    2021-07-07
  • 分析設計模式之模板方法Java實現(xiàn)

    分析設計模式之模板方法Java實現(xiàn)

    所謂模板方法模式,就是一個對模板的應用,就好比老師出試卷,每個人的試卷都是一樣的,這個原版試卷就是一個模板,可每個人寫在試卷上的答案都是不一樣的,這就是模板方法模式。它的主要用途在于將不變的行為從子類搬到超類,去除了子類中的重復代碼
    2021-06-06
  • MybatisPlus使用queryWrapper如何實現(xiàn)復雜查詢

    MybatisPlus使用queryWrapper如何實現(xiàn)復雜查詢

    這篇文章主要介紹了MybatisPlus使用queryWrapper如何實現(xiàn)復雜查詢,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教。
    2022-01-01
  • java compiler沒有1.8怎么解決

    java compiler沒有1.8怎么解決

    這篇文章主要介紹了java compiler沒有1.8的解決方法,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下
    2018-08-08
  • SpringBoot2.6.x升級后循環(huán)依賴及Swagger無法使用問題

    SpringBoot2.6.x升級后循環(huán)依賴及Swagger無法使用問題

    這篇文章主要為大家介紹了SpringBoot2.6.x升級后循環(huán)依賴及Swagger無法使用問題,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-06-06
  • Java線程同步、同步方法實例詳解

    Java線程同步、同步方法實例詳解

    本篇文章主要通過實例介紹了Java線程:線程的同步-同步方法,需要的朋友可以參考下
    2017-04-04
  • Java集合之Map接口的實現(xiàn)類精解

    Java集合之Map接口的實現(xiàn)類精解

    Map提供了一種映射關系,其中的元素是以鍵值對(key-value)的形式存儲的,能夠實現(xiàn)根據(jù)key快速查找value;Map中的鍵值對以Entry類型的對象實例形式存在;鍵(key值)不可重復,value值可以重復,一個value值可以和很多key值形成對應關系,每個建最多只能映射到一個值
    2021-09-09

最新評論