<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    我的家園

    我的家園

    如何避免死鎖--JCIPC10讀書筆記

    Posted on 2012-04-15 16:26 zljpp 閱讀(182) 評論(0)  編輯  收藏

    [本文是我對Java Concurrency In Practice C10的歸納和總結(jié). ?轉(zhuǎn)載請注明作者和出處, ?如有謬誤, 歡迎在評論中指正. ]

    如果多個線程以不同的順序持有多個鎖, 可能發(fā)生死鎖:

    ?

    public class AccountTrans {
    	public void transferMoney(Account fromAccount, Account toAccount, DollarAmount amount)
    			throws InsufficientFundsException {
    		synchronized (fromAccount) {
    			synchronized (toAccount) {
    				if (fromAccount.getBalance().compareTo(amount) < 0)
    					throw new InsufficientFundsException();
    				else {
    					fromAccount.debit(amount);
    					toAccount.credit(amount);
    				}
    			}
    		}
    	}
    }

    ?

    transferMoney方法先后鎖定fromAccount和toAccount對象. 如果2個線程以如下的方式調(diào)用transferMoney方法:

    A: transferMoney(myAccount, yourAccount, 10);?

    B: transferMoney(yourAccount, myAccount, 20);

    死鎖有可能就會發(fā)生.

    關(guān)鍵在于需要保證以相同的順序獲取多個鎖:

    ?

    public class AccountTrans {
    	// 額外的鎖
    	private static final Object tieLock = new Object();
    
    	public void transferMoney(final Account fromAcct, final Account toAcct, final DollarAmount amount)
    			throws InsufficientFundsException {
    		class Helper {
    			public void transfer() throws InsufficientFundsException {
    				if (fromAcct.getBalance().compareTo(amount) < 0)
    					throw new InsufficientFundsException();
    				else {
    					fromAcct.debit(amount);
    					toAcct.credit(amount);
    				}
    			}
    		}
    		// 計算fromAcct和toAcct的hashCode值
    		int fromHash = System.identityHashCode(fromAcct);
    		int toHash = System.identityHashCode(toAcct);
    
    		// 根據(jù)hashCode值確定獲取鎖的順序
    		if (fromHash < toHash) {
    			synchronized (fromAcct) {
    				synchronized (toAcct) {
    					new Helper().transfer();
    				}
    			}
    		} else if (fromHash > toHash) {
    			synchronized (toAcct) {
    				synchronized (fromAcct) {
    					new Helper().transfer();
    				}
    			}
    		} else {
    			// 當hashCode值相同時, 無法確定fromAcct和頭Acct鎖的獲取順序, 因此增加額外的鎖
    			synchronized (tieLock) {
    				synchronized (fromAcct) {
    					synchronized (toAcct) {
    						new Helper().transfer();
    					}
    				}
    			}
    		}
    	}
    }
    ?

    open call

    所謂open call是指在未持有鎖時調(diào)用外部方法. 持有鎖的時候調(diào)用外部方法, 如果被調(diào)用的方法需要獲取其他的鎖, 可能帶來死鎖的風險. 如果被調(diào)用的方法發(fā)生阻塞, 當前線程將長時間持有鎖, 其他等待獲取該鎖的線程就會被阻塞.

    因此我們應該盡量在未持有鎖的時候進行方法的調(diào)用.

    ?

    資源死鎖

    比如線程A持有數(shù)據(jù)庫D1的連接, 并等待獲取數(shù)據(jù)庫D2的連接. 而線程B持有數(shù)據(jù)庫D2的連接, 并等待獲取數(shù)據(jù)庫D1的連接. 此時就發(fā)生了死鎖.

    資源死鎖的另一種形式是線程饑餓死鎖, 參見第八章.

    ?

    避免死鎖

    1. 盡量不要同時持有多個鎖.

    2. 如果必須同時持有多個鎖, 那么保證以一致的順序獲取鎖.

    3. 盡量在未持有鎖的情況下進行方法的調(diào)用(open call).






    只有注冊用戶登錄后才能發(fā)表評論。


    網(wǎng)站導航:
     
    主站蜘蛛池模板: 日韩精品亚洲人成在线观看 | 四虎永久成人免费| 亚洲精品福利你懂| 成人免费视频小说| 成人精品国产亚洲欧洲| 免费国产a国产片高清网站| 边摸边脱吃奶边高潮视频免费| 国产猛烈高潮尖叫视频免费| 美女视频黄频a免费观看| 免费少妇a级毛片人成网| ww在线观视频免费观看w| 国产亚洲婷婷香蕉久久精品| 日本黄色动图免费在线观看| 久久精品国产亚洲AV无码麻豆| 永久免费视频网站在线观看| 亚洲av日韩av无码av| 欧洲精品免费一区二区三区| 四虎成人精品国产永久免费无码| 亚洲乱码国产一区网址| 最近免费mv在线观看动漫| 亚洲精品视频在线免费| 成人免费a级毛片无码网站入口| 亚洲欧美日韩中文字幕一区二区三区 | 亚洲最大黄色网址| 真实乱视频国产免费观看| 日本高清不卡中文字幕免费| 伊伊人成亚洲综合人网7777| 最近2019中文字幕免费大全5| 中中文字幕亚洲无线码| 亚洲av中文无码| 日日麻批免费40分钟无码| 亚洲黄页网在线观看| 亚洲日韩在线中文字幕第一页| 99热精品在线免费观看| 亚洲Av无码国产一区二区| 国产gv天堂亚洲国产gv刚刚碰| 全免费毛片在线播放| eeuss免费影院| 亚洲一区精彩视频| 中文字幕在线亚洲精品| 免费可以在线看A∨网站|