淺談Java由于不當(dāng)?shù)膱?zhí)行順序?qū)е碌乃梨i
我們來討論一個(gè)經(jīng)常存在的賬戶轉(zhuǎn)賬的問題。賬戶A要轉(zhuǎn)賬給賬戶B。為了保證在轉(zhuǎn)賬的過程中A和B不被其他的線程意外的操作,我們需要給A和B加鎖,然后再進(jìn)行轉(zhuǎn)賬操作, 我們看下轉(zhuǎn)賬的代碼:
public void transferMoneyDeadLock(Account from,Account to, int amount) throws InsufficientAmountException { synchronized (from){synchronized (to){ transfer(from,to,amount);} }}private void transfer(Account from,Account to, int amount) throws InsufficientAmountException { if(from.getBalance() < amount){throw new InsufficientAmountException(); }else{from.debit(amount);to.credit(amount); }}
看起來上面的程序好像沒有問題,因?yàn)槲覀兘ofrom和to都加了鎖,程序應(yīng)該可以很完美的按照我們的要求來執(zhí)行。
那如果我們考慮下面的一個(gè)場景:
A:transferMoneyDeadLock(accountA, accountB, 20)B:transferMoneyDeadLock(accountB, accountA, 10)
如果A和B同時(shí)執(zhí)行,則可能會產(chǎn)生A獲得了accountA的鎖,而B獲得了accountB的鎖。從而后面的代碼無法繼續(xù)執(zhí)行,從而導(dǎo)致了死鎖。
對于這樣的情況,我們有沒有什么好辦法來處理呢?
加入不管參數(shù)怎么傳遞,我們都先lock accountA再lock accountB是不是就不會出現(xiàn)死鎖的問題了呢?
我們看下代碼實(shí)現(xiàn):
private void transfer(Account from,Account to, int amount) throws InsufficientAmountException { if(from.getBalance() < amount){throw new InsufficientAmountException(); }else{from.debit(amount);to.credit(amount); }}public void transferMoney(Account from,Account to, int amount) throws InsufficientAmountException { int fromHash= System.identityHashCode(from); int toHash = System.identityHashCode(to); if(fromHash < toHash){synchronized (from){ synchronized (to){transfer(from,to, amount); }} }else if(fromHash < toHash){synchronized (to){ synchronized (from){transfer(from,to, amount); }} }else{synchronized (lock){synchronized (from) { synchronized (to) {transfer(from, to, amount); } }} }}
上面的例子中,我們使用了System.identityHashCode來獲得兩個(gè)賬號的hash值,通過比較hash值的大小來選定lock的順序。
如果兩個(gè)賬號的hash值恰好相等的情況下,我們引入了一個(gè)新的外部lock,從而保證同一時(shí)間只有一個(gè)線程能夠運(yùn)行內(nèi)部的方法,從而保證了任務(wù)的執(zhí)行而不產(chǎn)生死鎖。
以上就是淺談Java由于不當(dāng)?shù)膱?zhí)行順序?qū)е碌乃梨i的詳細(xì)內(nèi)容,更多關(guān)于Java由于不當(dāng)?shù)膱?zhí)行順序?qū)е碌乃梨i的資料請關(guān)注好吧啦網(wǎng)其它相關(guān)文章!
相關(guān)文章:
1. XML入門精解之結(jié)構(gòu)與語法2. CSS Hack大全-教你如何區(qū)分出IE6-IE10、FireFox、Chrome、Opera3. CSS3實(shí)例分享之多重背景的實(shí)現(xiàn)(Multiple backgrounds)4. 利用CSS3新特性創(chuàng)建透明邊框三角5. XML入門的常見問題(一)6. HTML5 Canvas繪制圖形從入門到精通7. 概述IE和SQL2k開發(fā)一個(gè)XML聊天程序8. HTML <!DOCTYPE> 標(biāo)簽9. HTML DOM setInterval和clearInterval方法案例詳解10. XML入門的常見問題(二)
