亚洲欧美日韩熟女|做爱高潮视频网址|国产一区二区三级片|国产Av中文字幕www.性色av|亚洲婷婷永久免费|国产高清中文字幕|欧美变态网站久re视频精品|人妻AV鲁丝第一页|天堂AV一区二区在线观看|综合 91在线精品

如何解決java線程死鎖? java線程鎖定代碼

2023-06-14

當(dāng)一個(gè)過程總是有一把鎖,其他過程都試圖得到這把鎖時(shí),它總是會被堵塞。當(dāng)過程A有鎖定L并想獲得鎖定M時(shí),過程B有鎖定M并試圖獲得鎖定L時(shí),那么這兩個(gè)過程將永遠(yuǎn)等待。這種情況是一種簡單的鎖定方式,其中許多過程總是等待,因?yàn)榄h(huán)路的鎖定依賴,所以有一把鎖。


1、鎖順序死鎖


以下是順序鎖的一個(gè)例子,代碼如下:


1 package deadLock;
 2 
 3 public class LeftRightDeadLock {
 4     private final Object left = new Object();
 5     private final Object right = new Object();
 6     
 7     public void leftRight() throws Exception{
 8         synchronized (left) {
 9             Thread.sleep(2000);
10             synchronized (right) {
11                 System.out.println("left to right");
12             }
13         }
14     }
15     
16     
17     public void rightLeft() throws Exception{
18         synchronized (right) {
19             Thread.sleep(2000);
20             synchronized (left) {
21                 System.out.println("right to left");
22             }
23         }
24     }
25     
26 }

View Code


1 package deadLock;
 2 
 3 public class LeftRightThread extends Thread {
 4 
 5     private LeftRightDeadLock d;
 6     public LeftRightThread(LeftRightDeadLock d){
 7         this.d = d;
 8     }
 9     @Override
10     public void run() {
11         try{
12             d.leftRight();
13         }catch(Exception ex){
14             ex.printStackTrace();
15         }
16     }
17 
18 }

View Code


1 package deadLock;
 2 
 3 public class RightLeftThread extends Thread {
 4 
 5     private LeftRightDeadLock d;
 6     public RightLeftThread(LeftRightDeadLock d){
 7         this.d = d;
 8     }
 9     @Override
10     public void run() {
11         try{
12             d.rightLeft();
13         }catch(Exception ex){
14             ex.printStackTrace();
15         }
16     }
17 
18 }

View Code


1 package deadLock;
 2 
 3 public class Main {
 4     public static void main(String[] args) {
 5         LeftRightDeadLock d = new LeftRightDeadLock();
 6         LeftRightThread t1 = new LeftRightThread(d);
 7         RightLeftThread t2 = new RightLeftThread(d);
 8         t1.start();
 9         t2.start();
10     }
11 }

View Code


過程t1有l(wèi)eft的鎖,并且嘗試得到right的鎖,而過程t2有right的鎖,并且嘗試得到left的鎖,因此產(chǎn)生死鎖。死鎖產(chǎn)生的原因是:兩個(gè)過程嘗試以不同的順序獲得相同的鎖,如果按相同的順序要求鎖定,則不會出現(xiàn)循環(huán)上鎖依賴,因此也不會產(chǎn)生死鎖。


假如所有的過程都按固定的順序獲取鎖,那么在系統(tǒng)中就不會出現(xiàn)鎖定順序死鎖的問題。


2、動(dòng)態(tài)鎖定順序死鎖


有時(shí),為了避免死鎖的發(fā)生,我們無法清楚地知道鎖定順序是否有足夠的控制權(quán),看看下面的轉(zhuǎn)帳代碼。


1 public class TransferAccounts {
 2     public void transferMoney(Account fromAccount, Account toAccount, double amount) throws Exception{
 3         synchronized (fromAccount) {
 4             synchronized (toAccount) {
 5                 if(fromAccount.getBalance() - amount < 0){
 6                     throw new Exception();
 7                 }
 8                 else{
 9                     fromAccount.setBalance(amount);
10                     toAccount.add(amount);
11                 }
12             }
13         }
14     }
15 }

View Code


1 public class Account {
 2     
 3     //額度
 4     private double balance;
 5 
 6     public double getBalance() {
 7         return balance;
 8     }
 9 
10     public void setBalance(double balance) {
11         this.balance = balance;
12     }
13     public void add(double amount){
14         balance  = amount;
15     }
16     public void subtra(double amount){
17         balance -= amount;
18     }
19     
20 }

View Code


以上代碼是資金從一個(gè)賬戶轉(zhuǎn)移到另一個(gè)賬戶的簡單實(shí)現(xiàn)。在開始轉(zhuǎn)賬之前,您應(yīng)該獲得這兩個(gè)Account對象的鎖,以確保兩個(gè)賬戶的余額通過原子更新??雌饋硭械倪^程都是按照順序鎖來獲取的,但實(shí)際上,鎖的順序取決于轉(zhuǎn)移函數(shù)transferMoney參數(shù)的順序,而這些參數(shù)則取決于外部輸入,如果兩個(gè)過程同時(shí)調(diào)用transferMoney,其中一個(gè)過程從X轉(zhuǎn)移到Y(jié),另一個(gè)過程從Y轉(zhuǎn)移到X轉(zhuǎn)移,那么死鎖就有可能發(fā)生:


進(jìn)程A:transferMoney(xAccount, yAccount);


進(jìn)程B:transferMoney(yAccount, xAccount);


為避免這種情況發(fā)生,必須按順序進(jìn)行鎖定。下面的代碼:


1 public class TransferAccounts {
 2     private static final Object tieLock = new Object();
 3 
 4     public void transfer(Account fromAccount, Account toAccount,
 5             double amount) throws Exception {
 6         if (fromAccount.getBalance() - amount < 0) {
 7             throw new Exception();
 8         } else {
 9             fromAccount.setBalance(amount);
10             toAccount.add(amount);
11         }
12     }
13     public void transferMoney(Account fromAccount, Account toAccount,
14             double amount) throws Exception{
15         int fromHash = fromAccount.hashCode();
16         int toHash = toAccount.hashCode();
17         if(fromHash < toHash){
18             synchronized (fromAccount) {
19                 synchronized (toAccount) {
20                     transfer(fromAccount, toAccount, amount);
21                 }
22             }
23         }else if(fromHash > toHash){
24             synchronized (toAccount) {
25                 synchronized (fromAccount) {
26                     transfer(fromAccount, toAccount, amount);
27                 }
28             }
29         }else {
30             synchronized (tieLock) {
31                 synchronized (fromAccount) {
32                     synchronized (toAccount) {
33                         transfer(fromAccount, toAccount, amount);
34                     }
35                 }
36             }
37         }
38     }
39     
40 }

View Code


在極少數(shù)情況下,兩個(gè)目標(biāo)可能有相對的hashCode值。此時(shí),需要添加額外的鎖。在獲得兩個(gè)Account的鎖之前,您必須首先獲得這個(gè)額外的鎖。然后清除死鎖。


3、避免和診斷死鎖


(1) 假如一個(gè)程序每次最多只能得到一把鎖,那么鎖的順序就不會被鎖定。


(2) 若要得到多個(gè)鎖,則在設(shè)計(jì)時(shí)必須考慮鎖的順序,若按固定順序得到鎖,則不會出現(xiàn)鎖的順序。


(3)支持定時(shí)鎖,例如在Lock類中顯示使用定時(shí)tryLock功能代替內(nèi)置鎖,顯示鎖可以指定一個(gè)超時(shí)限制,在等待超過一定時(shí)間后,tryLock將返回失敗信息。






本文為轉(zhuǎn)載內(nèi)容,我們尊重原作者對本文的作權(quán)。如有內(nèi)容錯(cuò)誤或侵權(quán)問題,歡迎原作者聯(lián)系我們更正或刪除內(nèi)容。

本文僅代表作者觀點(diǎn),版權(quán)歸原創(chuàng)者所有,如需轉(zhuǎn)載請?jiān)谖闹凶⒚鱽碓醇白髡呙帧?/p>

免責(zé)聲明:本文系轉(zhuǎn)載編輯文章,僅作分享之用。如分享內(nèi)容、圖片侵犯到您的版權(quán)或非授權(quán)發(fā)布,請及時(shí)與我們聯(lián)系進(jìn)行審核處理或刪除,您可以發(fā)送材料至郵箱:service@tojoy.com