Java并發(fā)編程預(yù)防死鎖過程詳解
這篇文章主要介紹了Java并發(fā)編程預(yù)防死鎖過程詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
在java并發(fā)編程領(lǐng)域已經(jīng)有技術(shù)大咖總結(jié)出了發(fā)生死鎖的條件,只有四個(gè)條件都發(fā)生時(shí)才會(huì)出現(xiàn)死鎖:
1.互斥,共享資源X和Y只能被一個(gè)線程占用
2.占有且等待,線程T1已經(jīng)取得共享資源X,在等待共享資源Y的時(shí)候,不釋放共享資源X
3.不可搶占,其他線程不能強(qiáng)行搶占線程T1占有的資源
4.循環(huán)等待,線程T1等待線程T2占有的資源,線程T2等待線程T1占有的資源,就是循環(huán)等待
只要能破壞其中一個(gè),就可以成功避免死鎖的發(fā)生,因?yàn)閷?duì)于共享資源我們要得就是互斥的效果,所以第一個(gè)條件是無法破壞的,所以可以從下面三個(gè)條件出手,具體實(shí)現(xiàn)方式:
1.對(duì)于“占用且等待”這個(gè)條件,我們可以一次性申請(qǐng)所有的資源,這樣就不存在等待了
class Allocator{ //通過破壞占有且等待條件避免死鎖現(xiàn)象的發(fā)生 private List<Object> als = new ArrayList<>(); //一次申請(qǐng)所有的資源 synchronized boolean apply(Object from, Object to){ if (als.contains(from) || als.contains(to)){ //只要存在一個(gè)賬戶被其他的業(yè)務(wù)鎖定則無法完成轉(zhuǎn)賬業(yè)務(wù) return false; }else { als.add(from); als.add(to); } return true; } //歸還資源 synchronized void free(Object from,Object to){ als.remove(from); als.remove(to); } } class Account { //actr應(yīng)該為單例 private Allocator actr; private int balance; //轉(zhuǎn)賬 void transfer(Account target, int amt){ //一次性申請(qǐng)轉(zhuǎn)出和轉(zhuǎn)入賬戶,直到成功 while (!actr.apply(this,target)); try{ //鎖定轉(zhuǎn)出賬戶 synchronized (this){ //鎖定轉(zhuǎn)入賬戶 synchronized (target){ if (this.balance > amt){ this.balance -= amt; target.balance += amt; } } } }finally { actr.free(this, target); } } }
2.對(duì)于“不可搶占”這個(gè)條件,占用部分資源的線程進(jìn)一步申請(qǐng)其他資源時(shí),如果申請(qǐng)不到,可以主動(dòng)釋放它所占有的資源,這樣不可搶占這個(gè)條件就破壞掉了
3.對(duì)于“循環(huán)等待”這個(gè)條件,可以靠按序申請(qǐng)資源來預(yù)防,所謂按序申請(qǐng),是指資源是有線性順序的,申請(qǐng)的時(shí)候可以先申請(qǐng)資源序號(hào)小的,再申請(qǐng)資源序號(hào)大的,這樣線性化后自然就不存在循環(huán)了
class Accounts{ private int id; private int balance; //轉(zhuǎn)賬 void transfer(Accounts target,int amt){ Accounts left = this; Accounts right = target; if (this.id > target.id){ left = target; right = this; } //鎖定序號(hào)小的賬戶 synchronized (left){ //鎖定序號(hào)大的賬戶 synchronized (right){ if (this.balance > amt){ this.balance -= amt; target.balance += amt; } } } } }
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
關(guān)于Maven混合配置私有倉(cāng)庫(kù)和公共倉(cāng)庫(kù)的問題
這篇文章主要介紹了Maven混合配置私有倉(cāng)庫(kù)和公共倉(cāng)庫(kù),通過實(shí)例代碼詳細(xì)介紹了私有和公共倉(cāng)庫(kù)混合配置的方法,需要的朋友可以參考下2022-06-06java?中如何實(shí)現(xiàn)?List?集合去重
這篇文章主要介紹了java?中如何實(shí)現(xiàn)?List?集合去重,List?去重指的是將?List?中的重復(fù)元素刪除掉的過程,下文操作操作過程介紹需要的小伙伴可以參考一下2022-05-059個(gè)小技巧讓你的Java if else看起來更優(yōu)雅
這篇文章主要給大家介紹了9個(gè)小技巧,通過這幾個(gè)小技巧可以讓你的Java if else看起來更優(yōu)雅,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-11-11SpringBoot連接MySql數(shù)據(jù)庫(kù)的原理及代碼示例
SpringBoot是一款流行的Java開發(fā)框架,它可以輕松地連接各種類型的數(shù)據(jù)庫(kù),包括關(guān)系型數(shù)據(jù)庫(kù)和非關(guān)系型數(shù)據(jù)庫(kù),本文將介紹SpringBoot是如何連接數(shù)據(jù)庫(kù)的,包括其原理和代碼示例,需要的朋友可以參考下2023-07-07Apache Commons Math3探索之快速傅立葉變換代碼示例
這篇文章主要介紹了Apache Commons Math3探索之快速傅立葉變換代碼示例,具有一定參考價(jià)值,需要的朋友可以了解下。2017-10-10Java Socket報(bào)錯(cuò)打開文件過多的問題
這篇文章主要介紹了Java Socket報(bào)錯(cuò)打開文件過多的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-05-05