由于不当的执行顺序导致的死锁
為了保證線程的安全,我們引入了加鎖機制,但是如果不加限制的使用加鎖,就有可能會導致順序死鎖(Lock-Ordering Deadlock)。上篇文章我們也提到了在線程詞中因為資源的不足而導致的資源死鎖(Resource Deadlock)。
本文將會討論一下順序死鎖的問題。
我們來討論一個經常存在的賬戶轉賬的問題。賬戶A要轉賬給賬戶B。為了保證在轉賬的過程中A和B不被其他的線程意外的操作,我們需要給A和B加鎖,然后再進行轉賬操作, 我們看下轉賬的代碼:
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);}}看起來上面的程序好像沒有問題,因為我們給from和to都加了鎖,程序應該可以很完美的按照我們的要求來執行。
那如果我們考慮下面的一個場景:
A:transferMoneyDeadLock(accountA, accountB, 20) B:transferMoneyDeadLock(accountB, accountA, 10)如果A和B同時執行,則可能會產生A獲得了accountA的鎖,而B獲得了accountB的鎖。從而后面的代碼無法繼續執行,從而導致了死鎖。
對于這樣的情況,我們有沒有什么好辦法來處理呢?
加入不管參數怎么傳遞,我們都先lock accountA再lock accountB是不是就不會出現死鎖的問題了呢?
我們看下代碼實現:
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來獲得兩個賬號的hash值,通過比較hash值的大小來選定lock的順序。
如果兩個賬號的hash值恰好相等的情況下,我們引入了一個新的外部lock,從而保證同一時間只有一個線程能夠運行內部的方法,從而保證了任務的執行而不產生死鎖。
本文的例子可以參考https://github.com/ddean2009/learn-java-concurrency/tree/master/accountTransferLock
更多精彩內容且看:
- 區塊鏈從入門到放棄系列教程-涵蓋密碼學,超級賬本,以太坊,Libra,比特幣等持續更新
- Spring Boot 2.X系列教程:七天從無到有掌握Spring Boot-持續更新
- Spring 5.X系列教程:滿足你對Spring5的一切想象-持續更新
- java程序員從小工到專家成神之路(2020版)-持續更新中,附詳細文章教程
更多內容請訪問 flydean的博客
超強干貨來襲 云風專訪:近40年碼齡,通宵達旦的技術人生總結
以上是生活随笔為你收集整理的由于不当的执行顺序导致的死锁的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java中有界队列的饱和策略(rejec
- 下一篇: 同步类的基础AbstractQueued