激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - Java并發之嵌套管程鎖死詳解

Java并發之嵌套管程鎖死詳解

2021-01-31 16:48六尺帳篷 Java教程

這篇文章主要介紹了Java并發之嵌套管程鎖死詳解,涉及嵌套管程鎖死的發生,實例等相關內容,具有一定參考價值,需要的朋友可以了解下。

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

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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的鎖(同時持有對象A的鎖)。
線程1決定等待另一個線程的信號再繼續。
線程1調用B.wait(),從而釋放了B對象上的鎖,但仍然持有對象A的鎖。

線程2需要同時持有對象A和對象B的鎖,才能向線程1發信號。
線程2無法獲得對象A上的鎖,因為對象A上的鎖當前正被線程1持有。
線程2一直被阻塞,等待線程1釋放對象A上的鎖。

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

我們看下面這個實際的例子:

java" id="highlighter_922014">
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//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,因為線程不會繼續調用monitorObject.wait(),那么一切都沒有問題 。但是如果isLocked等于true,調用lock()方法的線程會在monitorObject.wait()上阻塞。

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

(校對注:如果一個線程持有這種Lock的時候另一個線程執行了lock操作)當一個已經持有這種Lock的線程想調用unlock(),就會在unlock()方法進入synchronized(this)塊時阻塞。這會一直阻塞到在lock()方法中等待的線程離開synchronized(this)塊。但是,在unlock中isLocked變為false,monitorObject.notify()被執行之后,lock()中等待的線程才會離開synchronized(this)塊。

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

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

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

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
//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方法是怎么調用queueObject.wait()的,在方法內部有兩個synchronized塊,一個鎖定this,一個嵌在上一個synchronized塊內部,它鎖定的是局部變量queueObject。

當一個線程調用queueObject.wait()方法的時候,它僅僅釋放的是在queueObject對象實例的鎖,并沒有釋放”this”上面的鎖。
現在我們還有一個地方需要特別注意, unlock方法被聲明成了synchronized,這就相當于一個synchronized(this)塊。這就意味著,如果一個線程在lock()中等待,該線程將持有與this關聯的管程對象。所有調用unlock()的線程將會一直保持阻塞,等待著前面那個已經獲得this鎖的線程釋放this鎖,但這永遠也發生不了,因為只有某個線程成功地給lock()中等待的線程發送了信號,this上的鎖才會釋放,但只有執行unlock()方法才會發送這個信號。

因此,上面的公平鎖的實現會導致嵌套管程鎖死。

Nested Monitor Lockout vs. Deadlock

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

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

不同點歸納如下:

?
1
2
3
4
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,同時等待從線程2發來的信號,線程2需要鎖A來發信號給線程1。

總結

以上就是本文關于Java并發之嵌套管程鎖死詳解的全部內容,希望對大家有所幫助。有什么問題可以隨時留言,小編會及時回復大家的。感謝朋友們對本站的支持!

原文鏈接:http://www.jianshu.com/p/004468aa41ba

延伸 · 閱讀

精彩推薦
Weibo Article 1 Weibo Article 2 Weibo Article 3 Weibo Article 4 Weibo Article 5 Weibo Article 6 Weibo Article 7 Weibo Article 8 Weibo Article 9 Weibo Article 10 Weibo Article 11 Weibo Article 12 Weibo Article 13 Weibo Article 14 Weibo Article 15 Weibo Article 16 Weibo Article 17 Weibo Article 18 Weibo Article 19 Weibo Article 20 Weibo Article 21 Weibo Article 22 Weibo Article 23 Weibo Article 24 Weibo Article 25
主站蜘蛛池模板: 免费a级黄色片 | 国产69精品久久久久久 | 国产精品久久亚洲 | 久久久日韩精品一区二区三区 | 欧美成人鲁丝片在线观看 | 一区二区三区精品国产 | 97中文字幕第一一一页 | 色毛片 | 国产69精品久久久久9999不卡免费 | 羞羞的视频在线 | 色婷婷久久久久久 | 成人三级电影网 | lutube成人福利在线观看污 | 美女羞羞视频在线观看 | 欧美日韩亚洲视频 | 污污短视频 | 久久综合久久精品 | 男男羞羞视频网站国产 | 亚洲日韩中文字幕一区 | 欧美精品一区二区三区久久久 | 国产一区二区三区撒尿在线 | xnxx 日本19| 国产精品免费一区二区三区四区 | 国产人成免费爽爽爽视频 | 精精国产xxxx视频在线野外 | 欧美成人免费香蕉 | 色播视频在线播放 | 在线a视频 | 免费看污视频在线观看 | 黄色网电影| 成人毛片100部免费观看 | 精品久久久一 | 日本在线免费观看 | 高清国产午夜精品久久久久久 | 亚洲91网站 | 亚洲五码在线观看视频 | 国产91亚洲精品一区二区三区 | 91青青 | 极色品影院 | 九九热精 | 亚洲成人福利网站 |