Java并發(fā)編程預(yù)防死鎖過(guò)程詳解
這篇文章主要介紹了Java并發(fā)編程預(yù)防死鎖過(guò)程詳解,文中通過(guò)示例代碼介紹的非常詳細(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è)條件是無(wú)法破壞的,所以可以從下面三個(gè)條件出手,具體實(shí)現(xiàn)方式:
1.對(duì)于“占用且等待”這個(gè)條件,我們可以一次性申請(qǐng)所有的資源,這樣就不存在等待了
class Allocator{
//通過(guò)破壞占有且等待條件避免死鎖現(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ù)鎖定則無(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)資源來(lái)預(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)文章
一文掌握Spring Cookie和Session 是什么及區(qū)別介紹
Cookie和Session都是用于在客戶端和服務(wù)器之間傳遞信息的技術(shù),但它們的工作方式和使用場(chǎng)景有所不同,Cookie是在客戶端保存用戶信息的一種機(jī)制,而Session是在服務(wù)器端保存用戶信息的一種機(jī)制,本文介紹Spring Cookie和Session 是什么,感興趣的朋友一起看看吧2025-01-01
快速搭建一個(gè)SpringBoot項(xiàng)目(純小白搭建教程)
本文主要介紹了快速搭建一個(gè)SpringBoot項(xiàng)目,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-11-11
sin(x)如何求解的java代碼實(shí)現(xiàn)方法
這篇文章主要為大家介紹了sin(x)如何求解的java代碼實(shí)現(xiàn)方法示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-04-04
springboot結(jié)合前端實(shí)現(xiàn)網(wǎng)頁(yè)跳轉(zhuǎn)功能實(shí)例
今天處理Springboot統(tǒng)一異常攔截的時(shí)候,遇到了頁(yè)面跳轉(zhuǎn)的問(wèn)題,這篇文章主要給大家介紹了關(guān)于springboot結(jié)合前端實(shí)現(xiàn)網(wǎng)頁(yè)跳轉(zhuǎn)功能的相關(guān)資料,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-12-12
java List去掉重復(fù)元素的幾種方式(小結(jié))
這篇文章主要介紹了java List去掉重復(fù)元素的幾種方式,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-06-06
zuul集成Sentinel,完成對(duì)path映射的限流操作
這篇文章主要介紹了zuul集成Sentinel,完成對(duì)path映射的限流操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-06-06
Java集合之Set接口及其實(shí)現(xiàn)類(lèi)精解
set接口是繼承自Collection的子接口,特點(diǎn)是元素不重復(fù),存儲(chǔ)無(wú)序。在set接口的實(shí)現(xiàn)類(lèi)中添加重復(fù)元素是不會(huì)成功的,判斷兩個(gè)元素是否重復(fù)根據(jù)元素類(lèi)重寫(xiě)的2021-09-09

