Java并發(fā)編程預(yù)防死鎖過程詳解
這篇文章主要介紹了Java并發(fā)編程預(yù)防死鎖過程詳解,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
在java并發(fā)編程領(lǐng)域已經(jīng)有技術(shù)大咖總結(jié)出了發(fā)生死鎖的條件,只有四個條件都發(fā)生時才會出現(xiàn)死鎖:
1.互斥,共享資源X和Y只能被一個線程占用
2.占有且等待,線程T1已經(jīng)取得共享資源X,在等待共享資源Y的時候,不釋放共享資源X
3.不可搶占,其他線程不能強行搶占線程T1占有的資源
4.循環(huán)等待,線程T1等待線程T2占有的資源,線程T2等待線程T1占有的資源,就是循環(huán)等待
只要能破壞其中一個,就可以成功避免死鎖的發(fā)生,因為對于共享資源我們要得就是互斥的效果,所以第一個條件是無法破壞的,所以可以從下面三個條件出手,具體實現(xiàn)方式:
1.對于“占用且等待”這個條件,我們可以一次性申請所有的資源,這樣就不存在等待了
class Allocator{ //通過破壞占有且等待條件避免死鎖現(xiàn)象的發(fā)生 private List<Object> als = new ArrayList<>(); //一次申請所有的資源 synchronized boolean apply(Object from, Object to){ if (als.contains(from) || als.contains(to)){ //只要存在一個賬戶被其他的業(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){ //一次性申請轉(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.對于“不可搶占”這個條件,占用部分資源的線程進一步申請其他資源時,如果申請不到,可以主動釋放它所占有的資源,這樣不可搶占這個條件就破壞掉了
3.對于“循環(huán)等待”這個條件,可以靠按序申請資源來預(yù)防,所謂按序申請,是指資源是有線性順序的,申請的時候可以先申請資源序號小的,再申請資源序號大的,這樣線性化后自然就不存在循環(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; } //鎖定序號小的賬戶 synchronized (left){ //鎖定序號大的賬戶 synchronized (right){ if (this.balance > amt){ this.balance -= amt; target.balance += amt; } } } } }
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
9個小技巧讓你的Java if else看起來更優(yōu)雅
這篇文章主要給大家介紹了9個小技巧,通過這幾個小技巧可以讓你的Java if else看起來更優(yōu)雅,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-11-11SpringBoot連接MySql數(shù)據(jù)庫的原理及代碼示例
SpringBoot是一款流行的Java開發(fā)框架,它可以輕松地連接各種類型的數(shù)據(jù)庫,包括關(guān)系型數(shù)據(jù)庫和非關(guān)系型數(shù)據(jù)庫,本文將介紹SpringBoot是如何連接數(shù)據(jù)庫的,包括其原理和代碼示例,需要的朋友可以參考下2023-07-07Apache Commons Math3探索之快速傅立葉變換代碼示例
這篇文章主要介紹了Apache Commons Math3探索之快速傅立葉變換代碼示例,具有一定參考價值,需要的朋友可以了解下。2017-10-10