淺談Java由于不當的執(zhí)行順序導致的死鎖
我們來討論一個經常存在的賬戶轉賬的問題。賬戶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都加了鎖,程序應該可以很完美的按照我們的要求來執(zhí)行。
那如果我們考慮下面的一個場景:
A:transferMoneyDeadLock(accountA, accountB, 20) B:transferMoneyDeadLock(accountB, accountA, 10)
如果A和B同時執(zhí)行,則可能會產生A獲得了accountA的鎖,而B獲得了accountB的鎖。從而后面的代碼無法繼續(xù)執(zhí)行,從而導致了死鎖。
對于這樣的情況,我們有沒有什么好辦法來處理呢?
加入不管參數怎么傳遞,我們都先lock accountA再lock accountB是不是就不會出現(xiàn)死鎖的問題了呢?
我們看下代碼實現(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來獲得兩個賬號的hash值,通過比較hash值的大小來選定lock的順序。
如果兩個賬號的hash值恰好相等的情況下,我們引入了一個新的外部lock,從而保證同一時間只有一個線程能夠運行內部的方法,從而保證了任務的執(zhí)行而不產生死鎖。
以上就是淺談Java由于不當的執(zhí)行順序導致的死鎖的詳細內容,更多關于Java由于不當的執(zhí)行順序導致的死鎖的資料請關注腳本之家其它相關文章!
相關文章
使用redisTemplate的scan方式刪除批量key問題
這篇文章主要介紹了使用redisTemplate的scan方式刪除批量key問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-12-12
使用Prometheus+Grafana的方法監(jiān)控Springboot應用教程詳解
這篇文章主要介紹了用Prometheus+Grafana的方法監(jiān)控Springboot應用,本文通過實例代碼詳解給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-03-03
SpringBoot集成Spring Security的方法
Spring security,是一個強大的和高度可定制的身份驗證和訪問控制框架。這篇文章主要介紹了SpringBoot集成Spring Security的操作方法,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-07-07
智能 AI 代碼生成工具 Cursor 安裝和使用超詳細教程
Cursor.so 是一個集成了 GPT-4 的國內直接可以訪問的,優(yōu)秀而強大的免費代碼生成器,可以幫助你快速編寫、編輯和討論代碼,這篇文章主要介紹了智能 AI 代碼生成工具 Cursor 安裝和使用介紹,需要的朋友可以參考下2023-05-05

