首頁 >Java >java教程 >【JAVA】死鎖的產生與死鎖的解決

【JAVA】死鎖的產生與死鎖的解決

php是最好的语言
php是最好的语言原創
2018-08-06 13:44:333195瀏覽

                                            之後符號中使用所示的兩個鎖定符號上1# 含帳戶之間的轉帳情況

void transfer(Account from,Account to,int money){
    from.setAmount(from.getAmount()-money);
    to.setAmount(to.getAmount()+money);
}

單線程下,這段程式碼肯定沒問題的,但在多線程下存在問題

現在對其加鎖,加鎖後的程式碼如下

void transfer(Account from,Account to,int money){
    synchronized(from){
        synchronized(to){
            from.setAmount(from.getAmount()-money);
            to.setAmount(to.getAmount()+money);
        }
    }
}

synchronized,即對象鎖,第一個synchronized鎖住from對象,第二個synchronized鎖住to對象。

多執行緒情況下,在同一時刻多個執行緒中僅有一個執行緒能拿到這個物件鎖,對物件鎖裡面的程式碼段進行操​​作

但是加了物件鎖之後,可能存在死鎖!

transfer(a,b,100)和transfer(b,a,100)同時進行,即a向b轉帳的同時,b也在向a轉帳

【1】a向b轉賬,線程x拿到a這個物件鎖

【2】b向a轉賬,線程y拿到b這個物件鎖

操作【1】迫切需要b這個物件鎖,才能進行轉帳操作

操作【2】迫切需要a這個物件鎖,才能進行轉帳操作

兩個執行緒都在等待該群組中的其他執行緒釋放鎖,此時發生死鎖!

2、死鎖的解決

從那些方面下手呢?

【1】破除互斥等待

一般來說,我們為了程式的安全,必須給物件加上鎖,所以這個條件一般無法破除

【2 】破除hold and wait ,即佔有等待

可以一次取得所有的資源,範例程式碼中並不是一次性取得from和to這兩個資源的,而是分佈取得的。

方法一:給to加上一個很短的超時時間,一旦嘗試獲取to超時,則立即釋放一開始持有的from鎖,過一段時間後

再重新嘗試取得from與to鎖。是建議的方法

方法二:給這段程式碼加上全域鎖,可以確保from與to同時拿到,轉帳作業完成後,釋放這個全域鎖。是比較安全的,但是銀行的帳戶數目眾多,轉帳操作十分頻繁,使用這種方式勢必會造成性能的嚴重下降

【3】破除循環等待

按順序獲取資源,依照Account的id的大小進行轉帳的操作,id比較小的帳戶先進行轉帳操作,id比較大的帳戶後進行

轉帳操作。但現實生活中,有些事物是沒有id的,即沒有順序性,這個時候需要強制給其加上順序性。

【4】破除無法剝奪的等待

加入超時,不得已的方法,用戶的此次轉帳操作失敗,用戶的體驗不好 

個人推薦的解法:

犧牲使用者簡短的等待時間,使用【2】中的方法1

相關文章:

Java中死鎖的概念及解決方案

死鎖的概念與死鎖的條件

以上是【JAVA】死鎖的產生與死鎖的解決的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn