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

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

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

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

嵌套管程鎖死類似于死鎖, 下面是一個嵌套管程鎖死的場景:

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.

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

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

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

我們看下面這個實(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)榫€程不會繼續(xù)調(diào)用monitorObject.wait(),那么一切都沒有問題 。但是如果isLocked等于true,調(diào)用lock()方法的線程會在monitorObject.wait()上阻塞。

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

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

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

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

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

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

//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();
   }
  }
 }
}

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

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

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

Nested Monitor Lockout vs. Deadlock

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

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

不同點(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.

死鎖中,二個線程都在等待對方釋放鎖。

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

總結(jié)

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

相關(guān)文章

  • java 單例模式和工廠模式實(shí)例詳解

    java 單例模式和工廠模式實(shí)例詳解

    這篇文章主要介紹了Java設(shè)計(jì)模式編程中的單例模式和簡單工廠模式以及實(shí)例,使用設(shè)計(jì)模式編寫代碼有利于團(tuán)隊(duì)協(xié)作時(shí)程序的維護(hù),需要的朋友可以參考下
    2017-04-04
  • jfinal中stateless模式嵌入shiro驗(yàn)證的實(shí)現(xiàn)方式

    jfinal中stateless模式嵌入shiro驗(yàn)證的實(shí)現(xiàn)方式

    這篇文章主要介紹了jfinal中stateless模式嵌入shiro驗(yàn)證,今天,我們就來嘗試一種通過攔截器來實(shí)現(xiàn)的Stateless Jfinal嵌入方式,需要的朋友可以參考下
    2022-06-06
  • Log4j定時(shí)打印日志及添加模塊名配置的Java代碼實(shí)例

    Log4j定時(shí)打印日志及添加模塊名配置的Java代碼實(shí)例

    這篇文章主要介紹了Log4j定時(shí)打印日志及添加模塊名配置的Java代碼實(shí)例,Log4j是Apache的一個開源Java日志項(xiàng)目,需要的朋友可以參考下
    2016-01-01
  • Spring框架的環(huán)境搭建和測試實(shí)現(xiàn)

    Spring框架的環(huán)境搭建和測試實(shí)現(xiàn)

    這篇文章主要介紹了Spring框架的環(huán)境搭建和測試實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-10-10
  • 理解zookeeper選舉機(jī)制

    理解zookeeper選舉機(jī)制

    本文主要介紹了zookeeper選舉機(jī)制的相關(guān)知識,具有很好的參考價(jià)值,下面跟著小編一起來看下吧
    2017-02-02
  • SpringBoot登錄判斷過程代碼實(shí)例

    SpringBoot登錄判斷過程代碼實(shí)例

    這篇文章主要介紹了SpringBoot登錄判斷代碼實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-12-12
  • Java GC 機(jī)制與內(nèi)存分配策略詳解

    Java GC 機(jī)制與內(nèi)存分配策略詳解

    這篇文章主要介紹了Java GC 機(jī)制與內(nèi)存分配策略詳解的相關(guān)資料,需要的朋友可以參考下
    2017-02-02
  • 淺談springboot一個service內(nèi)組件的加載順序

    淺談springboot一個service內(nèi)組件的加載順序

    這篇文章主要介紹了springboot一個service內(nèi)組件的加載順序,具有很好的參考價(jià)值,希望對大家有所幫助。以上為個人經(jīng)驗(yàn),希望能給大家一個參考,也希望大家多多支持腳本之家
    2021-08-08
  • java中servlet實(shí)現(xiàn)登錄驗(yàn)證的方法

    java中servlet實(shí)現(xiàn)登錄驗(yàn)證的方法

    做web開發(fā),登錄驗(yàn)證是免不了的,今天學(xué)習(xí)了servlet的登錄驗(yàn)證,當(dāng)然是很簡單的,沒有使用session,request等作用域?qū)ο?,所以還是可以直接通過地址訪問網(wǎng)頁的。
    2013-05-05
  • Spring Core核心類庫的功能與應(yīng)用實(shí)踐分析

    Spring Core核心類庫的功能與應(yīng)用實(shí)踐分析

    本文詳細(xì)介紹了SpringCore核心類庫的功能、應(yīng)用實(shí)踐和底層原理,SpringCore提供了控制反轉(zhuǎn)(IOC)、依賴注入(DI)、Bean管理以及JNDI、定時(shí)任務(wù)等企業(yè)級功能,文章通過多個Java示例展示了SpringCore的應(yīng)用,感興趣的朋友跟隨小編一起看看吧
    2024-12-12

最新評論

宜城市| 遵化市| 古浪县| 建始县| 眉山市| 南川市| 贺州市| 利津县| 宝应县| 新巴尔虎左旗| 余庆县| 安仁县| 达尔| 奉化市| 浮山县| 堆龙德庆县| 丹巴县| 南昌县| 海城市| 延川县| 海口市| 石城县| 阿合奇县| 马边| 广宗县| 皋兰县| 淄博市| 报价| 类乌齐县| 高州市| 鹿泉市| 宜黄县| 永寿县| 饶河县| 西贡区| 襄垣县| 宜宾市| 莎车县| 西丰县| 乡城县| 博湖县|