欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java并發(fā)之嵌套管程鎖死詳解

 更新時(shí)間:2017年11月07日 08:44:17   作者:六尺帳篷  
這篇文章主要介紹了Java并發(fā)之嵌套管程鎖死詳解,涉及嵌套管程鎖死的發(fā)生,實(shí)例等相關(guān)內(nèi)容,具有一定參考價(jià)值,需要的朋友可以了解下。

·嵌套管程死鎖是如何發(fā)生的
·具體的嵌套管程死鎖的例子
·嵌套管程死鎖 vs 死鎖

嵌套管程鎖死類(lèi)似于死鎖, 下面是一個(gè)嵌套管程鎖死的場(chǎng)景:

Thread 1 synchronizes on A
Thread 1 synchronizes on B (while synchronized on A)
Thread 1 decides to wait for a signal from another thread before continuing
Thread 1 calls B.wait() thereby releasing the lock on B, but not A.

Thread 2 needs to lock both A and B (in that sequence)
    to send Thread 1 the signal.
Thread 2 cannot lock A, since Thread 1 still holds the lock on A.
Thread 2 remain blocked indefinately waiting for Thread1
    to release the lock on A

Thread 1 remain blocked indefinately waiting for the signal from
    Thread 2, thereby
    never releasing the lock on A, that must be released to make
    it possible for Thread 2 to send the signal to Thread 1, etc.

線(xiàn)程1獲得A對(duì)象的鎖。
線(xiàn)程1獲得對(duì)象B的鎖(同時(shí)持有對(duì)象A的鎖)。
線(xiàn)程1決定等待另一個(gè)線(xiàn)程的信號(hào)再繼續(xù)。
線(xiàn)程1調(diào)用B.wait(),從而釋放了B對(duì)象上的鎖,但仍然持有對(duì)象A的鎖。

線(xiàn)程2需要同時(shí)持有對(duì)象A和對(duì)象B的鎖,才能向線(xiàn)程1發(fā)信號(hào)。
線(xiàn)程2無(wú)法獲得對(duì)象A上的鎖,因?yàn)閷?duì)象A上的鎖當(dāng)前正被線(xiàn)程1持有。
線(xiàn)程2一直被阻塞,等待線(xiàn)程1釋放對(duì)象A上的鎖。

線(xiàn)程1一直阻塞,等待線(xiàn)程2的信號(hào),因此,不會(huì)釋放對(duì)象A上的鎖,
而線(xiàn)程2需要對(duì)象A上的鎖才能給線(xiàn)程1發(fā)信號(hào)……

我們看下面這個(gè)實(shí)際的例子:

//lock implementation with nested monitor lockout problem
public class Lock{
 protected MonitorObject monitorObject = new MonitorObject();
 protected boolean isLocked = false;
 public void lock() throws InterruptedException{
  synchronized(this){
   while(isLocked){
    synchronized(this.monitorObject){
      this.monitorObject.wait();
    }
   }
   isLocked = true;
  }
 }
 public void unlock(){
  synchronized(this){
   this.isLocked = false;
   synchronized(this.monitorObject){
    this.monitorObject.notify();
   }
  }
 }
}

可以看到,lock()方法首先在”this”上同步,然后在monitorObject上同步。如果isLocked等于false,因?yàn)榫€(xiàn)程不會(huì)繼續(xù)調(diào)用monitorObject.wait(),那么一切都沒(méi)有問(wèn)題 。但是如果isLocked等于true,調(diào)用lock()方法的線(xiàn)程會(huì)在monitorObject.wait()上阻塞。

這里的問(wèn)題在于,調(diào)用monitorObject.wait()方法只釋放了monitorObject上的管程對(duì)象,而與”this“關(guān)聯(lián)的管程對(duì)象并沒(méi)有釋放。換句話(huà)說(shuō),這個(gè)剛被阻塞的線(xiàn)程仍然持有”this”上的鎖。

(校對(duì)注:如果一個(gè)線(xiàn)程持有這種Lock的時(shí)候另一個(gè)線(xiàn)程執(zhí)行了lock操作)當(dāng)一個(gè)已經(jīng)持有這種Lock的線(xiàn)程想調(diào)用unlock(),就會(huì)在unlock()方法進(jìn)入synchronized(this)塊時(shí)阻塞。這會(huì)一直阻塞到在lock()方法中等待的線(xiàn)程離開(kāi)synchronized(this)塊。但是,在unlock中isLocked變?yōu)閒alse,monitorObject.notify()被執(zhí)行之后,lock()中等待的線(xiàn)程才會(huì)離開(kāi)synchronized(this)塊。

簡(jiǎn)而言之,在lock方法中等待的線(xiàn)程需要其它線(xiàn)程成功調(diào)用unlock方法來(lái)退出lock方法,但是,在lock()方法離開(kāi)外層同步塊之前,沒(méi)有線(xiàn)程能成功執(zhí)行unlock()。

結(jié)果就是,任何調(diào)用lock方法或unlock方法的線(xiàn)程都會(huì)一直阻塞。這就是嵌套管程鎖死。

具體的嵌套管程死鎖的例子

例如,如果你準(zhǔn)備實(shí)現(xiàn)一個(gè)公平鎖。你可能希望每個(gè)線(xiàn)程在它們各自的QueueObject上調(diào)用wait(),這樣就可以每次喚醒一個(gè)線(xiàn)程。

//Fair Lock implementation with nested monitor lockout problem
public class FairLock {
 private boolean      isLocked    = false;
 private Thread      lockingThread = null;
 private List<QueueObject> waitingThreads =
      new ArrayList<QueueObject>();
 public void lock() throws InterruptedException{
  QueueObject queueObject = new QueueObject();
  synchronized(this){
   waitingThreads.add(queueObject);
   while(isLocked || waitingThreads.get(0) != queueObject){
    synchronized(queueObject){
     try{
      queueObject.wait();
     }catch(InterruptedException e){
      waitingThreads.remove(queueObject);
      throw e;
     }
    }
   }
   waitingThreads.remove(queueObject);
   isLocked = true;
   lockingThread = Thread.currentThread();
  }
 }
 public synchronized void unlock(){
  if(this.lockingThread != Thread.currentThread()){
   throw new IllegalMonitorStateException(
    "Calling thread has not locked this lock");
  }
  isLocked   = false;
  lockingThread = null;
  if(waitingThreads.size() > 0){
   QueueObject queueObject = waitingThread.get(0);
   synchronized(queueObject){
    queueObject.notify();
   }
  }
 }
}

乍看之下,嗯,很好,但是請(qǐng)注意lock方法是怎么調(diào)用queueObject.wait()的,在方法內(nèi)部有兩個(gè)synchronized塊,一個(gè)鎖定this,一個(gè)嵌在上一個(gè)synchronized塊內(nèi)部,它鎖定的是局部變量queueObject。

當(dāng)一個(gè)線(xiàn)程調(diào)用queueObject.wait()方法的時(shí)候,它僅僅釋放的是在queueObject對(duì)象實(shí)例的鎖,并沒(méi)有釋放”this”上面的鎖。
現(xiàn)在我們還有一個(gè)地方需要特別注意, unlock方法被聲明成了synchronized,這就相當(dāng)于一個(gè)synchronized(this)塊。這就意味著,如果一個(gè)線(xiàn)程在lock()中等待,該線(xiàn)程將持有與this關(guān)聯(lián)的管程對(duì)象。所有調(diào)用unlock()的線(xiàn)程將會(huì)一直保持阻塞,等待著前面那個(gè)已經(jīng)獲得this鎖的線(xiàn)程釋放this鎖,但這永遠(yuǎn)也發(fā)生不了,因?yàn)橹挥心硞€(gè)線(xiàn)程成功地給lock()中等待的線(xiàn)程發(fā)送了信號(hào),this上的鎖才會(huì)釋放,但只有執(zhí)行unlock()方法才會(huì)發(fā)送這個(gè)信號(hào)。

因此,上面的公平鎖的實(shí)現(xiàn)會(huì)導(dǎo)致嵌套管程鎖死。

Nested Monitor Lockout vs. Deadlock

嵌套管程鎖死與死鎖很像:都是線(xiàn)程最后被一直阻塞著互相等待。

但是兩者又不完全相同。在死鎖中我們已經(jīng)對(duì)死鎖有了個(gè)大概的解釋?zhuān)梨i通常是因?yàn)閮蓚€(gè)線(xiàn)程獲取鎖的順序不一致造成的,線(xiàn)程1鎖住A,等待獲取B,線(xiàn)程2已經(jīng)獲取了B,再等待獲取A。如死鎖避免中所說(shuō)的,死鎖可以通過(guò)總是以相同的順序獲取鎖來(lái)避免。但是發(fā)生嵌套管程鎖死時(shí)鎖獲取的順序是一致的。線(xiàn)程1獲得A和B,然后釋放B,等待線(xiàn)程2的信號(hào)。線(xiàn)程2需要同時(shí)獲得A和B,才能向線(xiàn)程1發(fā)送信號(hào)。所以,一個(gè)線(xiàn)程在等待喚醒,另一個(gè)線(xiàn)程在等待想要的鎖被釋放。

不同點(diǎn)歸納如下:

In deadlock, two threads are waiting for each other to release locks.
In nested monitor lockout, Thread 1 is holding a lock A, and waits
for a signal from Thread 2. Thread 2 needs the lock A to send the
signal to Thread 1.

死鎖中,二個(gè)線(xiàn)程都在等待對(duì)方釋放鎖。

嵌套管程鎖死中,線(xiàn)程1持有鎖A,同時(shí)等待從線(xiàn)程2發(fā)來(lái)的信號(hào),線(xiàn)程2需要鎖A來(lái)發(fā)信號(hào)給線(xiàn)程1。

總結(jié)

以上就是本文關(guān)于Java并發(fā)之嵌套管程鎖死詳解的全部?jī)?nèi)容,希望對(duì)大家有所幫助。感興趣的朋友可以繼續(xù)參閱本站:java并發(fā)編程之cas詳解、java實(shí)現(xiàn)遍歷樹(shù)形菜單兩種實(shí)現(xiàn)代碼分享等,有什么問(wèn)題可以隨時(shí)留言,小編會(huì)及時(shí)回復(fù)大家的。感謝朋友們對(duì)本站的支持!

相關(guān)文章

  • 淺析Java 對(duì)象引用和對(duì)象本身

    淺析Java 對(duì)象引用和對(duì)象本身

    這篇文章主要介紹了Java 對(duì)象引用和對(duì)象本身的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)Java,感興趣的朋友可以了解下
    2020-08-08
  • Mybatis-Plus中的MetaObjectHandler組件的使用

    Mybatis-Plus中的MetaObjectHandler組件的使用

    MetaObjectHandler是Mybatis-Plus中一個(gè)實(shí)用組件,專(zhuān)門(mén)用于自動(dòng)處理實(shí)體對(duì)象中的特定字段,如創(chuàng)建時(shí)間、更新時(shí)間、創(chuàng)建人和修改人等,該接口允許開(kāi)發(fā)者在不修改業(yè)務(wù)代碼的情況下,實(shí)現(xiàn)自動(dòng)填充功能,極大地簡(jiǎn)化了代碼的復(fù)雜性,感興趣的可以了解一下
    2024-10-10
  • Jenkins 關(guān)閉和重啟詳細(xì)介紹及實(shí)現(xiàn)

    Jenkins 關(guān)閉和重啟詳細(xì)介紹及實(shí)現(xiàn)

    這篇文章主要介紹了Jenkins的關(guān)閉、重啟的相關(guān)資料,用jar -jar jenkins.war來(lái)啟動(dòng)jenkins服務(wù)器,那么我們?nèi)绾侮P(guān)閉或者重啟jenkins服務(wù)器呢,這里就給出實(shí)現(xiàn)的方法,需要的朋友可以參考下
    2016-11-11
  • SpringBoot超詳細(xì)講解@Enable*注解和@Import

    SpringBoot超詳細(xì)講解@Enable*注解和@Import

    這篇文章主要介紹了SpringBoot?@Enable*注解和@Import,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-07-07
  • SpringCache快速使用及入門(mén)案例

    SpringCache快速使用及入門(mén)案例

    Spring Cache 是Spring 提供的一整套的緩存解決方案,它不是具體的緩存實(shí)現(xiàn),本文主要介紹了SpringCache快速使用及入門(mén)案例,感興趣的可以了解一下
    2023-08-08
  • 詳解Spring MVC/Boot 統(tǒng)一異常處理最佳實(shí)踐

    詳解Spring MVC/Boot 統(tǒng)一異常處理最佳實(shí)踐

    在 Web 開(kāi)發(fā)中, 我們經(jīng)常會(huì)需要處理各種異常,這篇文章主要介紹了詳解Spring MVC/Boot 統(tǒng)一異常處理最佳實(shí)踐,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-01-01
  • 不寫(xiě)mybatis的@Param有的報(bào)錯(cuò)有的卻不報(bào)錯(cuò)問(wèn)題分析

    不寫(xiě)mybatis的@Param有的報(bào)錯(cuò)有的卻不報(bào)錯(cuò)問(wèn)題分析

    這篇文章主要為大家介紹了不寫(xiě)mybatis的@Param有的報(bào)錯(cuò)有的卻不報(bào)錯(cuò)問(wèn)題分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-09-09
  • Java中如何使用?byte?數(shù)組作為?Map?的?key

    Java中如何使用?byte?數(shù)組作為?Map?的?key

    本文將討論在使用HashMap時(shí),當(dāng)byte數(shù)組作為key時(shí)所遇到的問(wèn)題及其解決方案,介紹使用String和List這兩種數(shù)據(jù)結(jié)構(gòu)作為臨時(shí)解決方案的方法,感興趣的朋友跟隨小編一起看看吧
    2023-06-06
  • android中判斷服務(wù)或者進(jìn)程是否存在實(shí)例

    android中判斷服務(wù)或者進(jìn)程是否存在實(shí)例

    本篇文章主要介紹了android中判斷服務(wù)或者進(jìn)程是否存在實(shí)例,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-05-05
  • 解析Runtime中shutdown hook的使用詳解

    解析Runtime中shutdown hook的使用詳解

    本篇文章是對(duì)解析Runtime中shutdown hook的使用進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05

最新評(píng)論