<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 閱讀(181) 評論(0)  編輯  收藏

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

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

    ?

    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個線程以如下的方式調用transferMoney方法:

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

    B: transferMoney(yourAccount, myAccount, 20);

    死鎖有可能就會發生.

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

    ?

    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);
    
    		// 根據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是指在未持有鎖時調用外部方法. 持有鎖的時候調用外部方法, 如果被調用的方法需要獲取其他的鎖, 可能帶來死鎖的風險. 如果被調用的方法發生阻塞, 當前線程將長時間持有鎖, 其他等待獲取該鎖的線程就會被阻塞.

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

    ?

    資源死鎖

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

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

    ?

    避免死鎖

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

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

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






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


    網站導航:
     
    主站蜘蛛池模板: mm1313亚洲精品无码又大又粗 | 99精品一区二区免费视频| 国产免费午夜a无码v视频| 亚洲人成在线精品| 13一14周岁毛片免费| 亚洲日本中文字幕| 免费无码一区二区三区| 亚洲伦另类中文字幕| 久久国产精品免费观看| 97久久精品亚洲中文字幕无码| 久久久精品午夜免费不卡| 亚洲AV无码一区二区三区系列| 国产免费无码一区二区| 亚洲国产成人一区二区精品区 | 伊人久久亚洲综合| 最近免费mv在线观看动漫| 亚洲成人免费在线| 国内精品免费麻豆网站91麻豆| 亚洲videosbestsex日本| 韩国18福利视频免费观看| 国产AV日韩A∨亚洲AV电影 | 久久国产精品一区免费下载| 西西人体44rt高清亚洲| 99久久久国产精品免费无卡顿| 亚洲一级免费毛片| 国产一级特黄高清免费大片| 九一在线完整视频免费观看| 亚洲va无码手机在线电影| 99在线视频免费| 亚洲av无码一区二区三区观看| 国内大片在线免费看| 日本高清不卡中文字幕免费| 亚洲国产精品久久久天堂| 亚洲香蕉免费有线视频| 国产成人精品日本亚洲语音 | 亚洲精品国产高清在线观看| 99re免费99re在线视频手机版| 亚洲人成毛片线播放| 日本午夜免费福利视频| 好猛好深好爽好硬免费视频| 亚洲福利一区二区三区|