日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術文章
文章詳情頁

詳解Java Slipped Conditions

瀏覽:22日期:2022-08-17 18:01:51

所謂Slipped conditions,就是說, 從一個線程檢查某一特定條件到該線程操作此條件期間,這個條件已經被其它線程改變,導致第一個線程在該條件上執行了錯誤的操作。這里有一個簡單的例子:

public class Lock { private boolean isLocked = true; public void lock(){ synchronized(this){ while(isLocked){ try{ this.wait(); } catch(InterruptedException e){ //do nothing, keep waiting } } } synchronized(this){ isLocked = true; } } public synchronized void unlock(){ isLocked = false; this.notify(); }}

我們可以看到,lock()方法包含了兩個同步塊。第一個同步塊執行wait操作直到isLocked變為false才退出,第二個同步塊將isLocked置為true,以此來鎖住這個Lock實例避免其它線程通過lock()方法。

我們可以設想一下,假如在某個時刻isLocked為false, 這個時候,有兩個線程同時訪問lock方法。如果第一個線程先進入第一個同步塊,這個時候它會發現isLocked為false,若此時允許第二個線程執行,它也進入第一個同步塊,同樣發現isLocked是false。現在兩個線程都檢查了這個條件為false,然后它們都會繼續進入第二個同步塊中并設置isLocked為true。

這個場景就是slipped conditions的例子,兩個線程檢查同一個條件, 然后退出同步塊,因此在這兩個線程改變條件之前,就允許其它線程來檢查這個條件。換句話說,條件被某個線程檢查到該條件被此線程改變期間,這個條件已經被其它線程改變過了。

為避免slipped conditions,條件的檢查與設置必須是原子的,也就是說,在第一個線程檢查和設置條件期間,不會有其它線程檢查這個條件。

解決上面問題的方法很簡單,只是簡單的把isLocked = true這行代碼移到第一個同步塊中,放在while循環后面即可:

public class Lock { private boolean isLocked = true; public void lock(){ synchronized(this){ while(isLocked){ try{ this.wait(); } catch(InterruptedException e){ //do nothing, keep waiting } } isLocked = true; } } public synchronized void unlock(){ isLocked = false; this.notify(); }}

現在檢查和設置isLocked條件是在同一個同步塊中原子地執行了。

一個更現實的例子

也許你會說,我才不可能寫這么挫的代碼,還覺得slipped conditions是個相當理論的問題。但是第一個簡單的例子只是用來更好的展示slipped conditions。

饑餓和公平中實現的公平鎖也許是個更現實的例子。再看下嵌套管程鎖死中那個幼稚的實現,如果我們試圖解決其中的嵌套管程鎖死問題,很容易產生slipped conditions問題。首先讓我們看下嵌套管程鎖死中的例子:

//Fair Lock implementation with nested monitor lockout problempublic class FairLock { private boolean isLocked = false; private Thread lockingThread = null; private List waitingThreads = new ArrayList(); 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(); } } }}1public class QueueObject {}

我們可以看到synchronized(queueObject)及其中的queueObject.wait()調用是嵌在synchronized(this)塊里面的,這會導致嵌套管程鎖死問題。為避免這個問題,我們必須將synchronized(queueObject)塊移出synchronized(this)塊。移出來之后的代碼可能是這樣的:

//Fair Lock implementation with slipped conditions problempublic class FairLock { private boolean isLocked = false; private Thread lockingThread = null; private List waitingThreads = new ArrayList(); public void lock() throws InterruptedException{ QueueObject queueObject = new QueueObject(); synchronized(this){ waitingThreads.add(queueObject); } boolean mustWait = true; while(mustWait){ synchronized(this){ mustWait = isLocked || waitingThreads.get(0) != queueObject; } synchronized(queueObject){ if(mustWait){ try{ queueObject.wait(); }catch(InterruptedException e){ waitingThreads.remove(queueObject); throw e; } } } } synchronized(this){ waitingThreads.remove(queueObject); isLocked = true; lockingThread = Thread.currentThread(); } }}

注意:因為我只改動了lock()方法,這里只展現了lock方法。

現在lock()方法包含了3個同步塊。

第一個,synchronized(this)塊通過mustWait = isLocked || waitingThreads.get(0) != queueObject檢查內部變量的值。

第二個,synchronized(queueObject)塊檢查線程是否需要等待。也有可能其它線程在這個時候已經解鎖了,但我們暫時不考慮這個問題。我們就假設這個鎖處在解鎖狀態,所以線程會立馬退出synchronized(queueObject)塊。

第三個,synchronized(this)塊只會在mustWait為false的時候執行。它將isLocked重新設回true,然后離開lock()方法。

設想一下,在鎖處于解鎖狀態時,如果有兩個線程同時調用lock()方法會發生什么。首先,線程1會檢查到isLocked為false,然后線程2同樣檢查到isLocked為false。接著,它們都不會等待,都會去設置isLocked為true。這就是slipped conditions的一個最好的例子。

解決Slipped Conditions問題

要解決上面例子中的slipped conditions問題,最后一個synchronized(this)塊中的代碼必須向上移到第一個同步塊中。為適應這種變動,代碼需要做點小改動。下面是改動過的代碼:

//Fair Lock implementation without nested monitor lockout problem,//but with missed signals problem.public class FairLock { private boolean isLocked = false; private Thread lockingThread = null; private List waitingThreads = new ArrayList(); public void lock() throws InterruptedException{ QueueObject queueObject = new QueueObject(); synchronized(this){ waitingThreads.add(queueObject); } boolean mustWait = true; while(mustWait){ synchronized(this){ mustWait = isLocked || waitingThreads.get(0) != queueObject; if(!mustWait){ waitingThreads.remove(queueObject); isLocked = true; lockingThread = Thread.currentThread(); return; } } synchronized(queueObject){ if(mustWait){ try{ queueObject.wait(); }catch(InterruptedException e){ waitingThreads.remove(queueObject); throw e; } } } } }}

我們可以看到對局部變量mustWait的檢查與賦值是在同一個同步塊中完成的。還可以看到,即使在synchronized(this)塊外面檢查了mustWait,在while(mustWait)子句中,mustWait變量從來沒有在synchronized(this)同步塊外被賦值。當一個線程檢查到mustWait是false的時候,它將自動設置內部的條件(isLocked),所以其它線程再來檢查這個條件的時候,它們就會發現這個條件的值現在為true了。

synchronized(this)塊中的return;語句不是必須的。這只是個小小的優化。如果一個線程肯定不會等待(即mustWait為false),那么就沒必要讓它進入到synchronized(queueObject)同步塊中和執行if(mustWait)子句了。

細心的讀者可能會注意到上面的公平鎖實現仍然有可能丟失信號。設想一下,當該FairLock實例處于鎖定狀態時,有個線程來調用lock()方法。執行完第一個 synchronized(this)塊后,mustWait變量的值為true。再設想一下調用lock()的線程是通過搶占式的,擁有鎖的那個線程那個線程此時調用了unlock()方法,但是看下之前的unlock()的實現你會發現,它調用了queueObject.notify()。但是,因為lock()中的線程還沒有來得及調用queueObject.wait(),所以queueObject.notify()調用也就沒有作用了,信號就丟失掉了。如果調用lock()的線程在另一個線程調用queueObject.notify()之后調用queueObject.wait(),這個線程會一直阻塞到其它線程調用unlock方法為止,但這永遠也不會發生。

公平鎖實現的信號丟失問題在饑餓和公平一文中我們已有過討論,把QueueObject轉變成一個信號量,并提供兩個方法:doWait()和doNotify()。這些方法會在QueueObject內部對信號進行存儲和響應。用這種方式,即使doNotify()在doWait()之前調用,信號也不會丟失。

以上就是詳解Java Slipped Conditions的詳細內容,更多關于Java Slipped Conditions的資料請關注好吧啦網其它相關文章!

標簽: Java
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
欧美aa在线视频| 国产一区二区三区久久 | 美女国产精品| 久久国产精品久久w女人spa| 免费毛片在线不卡| 天堂а√在线最新版中文在线| 自拍日韩欧美| 日韩不卡免费高清视频| 国产精品一级| 日韩精品久久久久久| 国产精品毛片一区二区三区| 亚洲特级毛片| 久久精品av| 亚洲天堂黄色| 91精品91| 亚洲欧美日本日韩| 99国产一区| 色偷偷偷在线视频播放| 国产精品v日韩精品v欧美精品网站 | 亚洲精品第一| 香蕉久久久久久久av网站| 群体交乱之放荡娇妻一区二区| 亚洲三级网址| 欧美午夜三级| 91精品美女| 精品一区二区三区中文字幕 | 日韩不卡一区二区三区| 亚洲一卡久久| 视频一区二区三区在线| 久久福利一区| 午夜性色一区二区三区免费视频| 亚洲精品一级| 国产精品av久久久久久麻豆网| 福利在线免费视频| 亚洲精品大片| 国产欧美日韩一级| 久久精品青草| 欧美极品中文字幕| 亚洲手机在线| 欧美精品影院| 亚洲综合专区| 日韩福利视频导航| av资源亚洲| 午夜久久一区| 99国产精品久久久久久久| 日韩精品久久理论片| 欧美天堂亚洲电影院在线观看| 久久亚洲国产精品一区二区| 亚洲一区日韩在线| 精品国产午夜| 亚洲精品**中文毛片| 久久国产电影| 爽好多水快深点欧美视频| 日韩一区二区三区四区五区| 国产亚洲高清一区| 国产精品成久久久久| 精品伊人久久久| 亚洲精品.com| 亚洲涩涩av| 国产福利资源一区| 国产视频网站一区二区三区| 日本少妇精品亚洲第一区| 欧美久久久网站| 国产成年精品| 五月综合激情| 日韩不卡一二三区| 色婷婷综合网| 久久不射网站| 欧美欧美黄在线二区| 另类小说一区二区三区| 99视频精品全部免费在线视频| 黄色aa久久| 国产综合色产| 天堂久久av| 水蜜桃久久夜色精品一区| 美女网站一区| 91精品国产成人观看| 国产欧美日韩精品高清二区综合区 | 精品99久久| 久久一区亚洲| 久久久亚洲欧洲日产| 久久激情网站| 日韩国产欧美| 中文字幕视频精品一区二区三区| 久久只有精品| 色综合www| 视频一区二区欧美| 亚洲在线久久| 日韩精品视频一区二区三区| 国内精品福利| 日韩精品第一| 国语对白精品一区二区| 97精品国产一区二区三区| 亚洲视频播放| 日韩精品一区二区三区中文| 国产午夜一区| 日韩在线中文| 在线精品视频一区| 97国产成人高清在线观看| 免费福利视频一区二区三区| 久久精品伊人| 国产亚洲人成a在线v网站| 久久久水蜜桃av免费网站| 日韩不卡一区二区三区| 深夜视频一区二区| 久久国产人妖系列| 国产精品女主播一区二区三区| 久久免费精品| 亚洲精品黄色| 亚洲在线观看| 国产亚洲一卡2卡3卡4卡新区| 亚洲区国产区| 在线精品亚洲| 性欧美videohd高精| 亚洲在线电影| 久久久成人网| 国产精品igao视频网网址不卡日韩 | 日本韩国欧美超级黄在线观看| 黄色国产精品| 精品九九久久| 国产传媒在线| 久久国产成人午夜av影院宅| 日韩欧美午夜| 亚洲精品伊人| 精品视频网站| 国产精品一区二区精品视频观看 | 久久九九精品| 精品久久久久中文字幕小说| 日本欧美一区二区| 午夜在线精品| 亚洲人成毛片在线播放女女| 精品久久在线| 国产伦一区二区三区| 日韩和欧美一区二区| 国产一区2区| 久久精品一区二区三区中文字幕| 不卡一区2区| 爽好久久久欧美精品| 黑丝一区二区三区| 国产亚洲精品v| 亚洲毛片视频| 国产精品hd| 伊人久久视频| 一区在线观看| 日韩精品导航| 久久精品国产亚洲aⅴ| 岛国av在线网站| 偷拍欧美精品| 日本在线视频一区二区| 免费视频一区二区| 欧美综合社区国产| 国产一区二区三区天码| 亚洲一级黄色| 蜜桃传媒麻豆第一区在线观看| 国内不卡的一区二区三区中文字幕| 麻豆精品蜜桃| 最新国产精品视频| 黄毛片在线观看| 99视频精品| 日韩一区自拍| 成人国产精品久久| 91伊人久久| 视频精品一区二区| 久久久久久一区二区| 91视频精品| 免费黄色成人| 日韩精品午夜视频| 国产在线观看www| 国产精品一区二区免费福利视频 | 精品免费av| 欧美日韩尤物久久| 国产伦乱精品| 亚洲欧洲日韩精品在线| 国产一区二区三区黄网站| 亚洲+小说+欧美+激情+另类| 日韩一级精品| 麻豆国产精品777777在线| 在线看片国产福利你懂的| 91看片一区| 秋霞影院一区二区三区| 日韩视频网站在线观看| 久久99偷拍| 日韩欧美精品一区| 精品国产一级| 国产一在线精品一区在线观看| 亚洲人妖在线| 精品中文字幕一区二区三区四区| 成人av动漫在线观看| 日韩在线中文| 亚洲最新av| 国产精品超碰| 亚洲风情在线资源| 日本电影久久久| 日本免费在线视频不卡一不卡二| 欧美在线黄色| 97久久亚洲| 韩国女主播一区二区三区| 日本va欧美va欧美va精品| 狠狠爱成人网| 国产亚洲欧美日韩精品一区二区三区 |