導航:首頁 > 編程語言 > java中死鎖

java中死鎖

發布時間:2022-09-03 12:24:51

java開發中,什麼是死鎖(Deadlock)如何分析和避免死鎖

死鎖是指兩個以上的線程永遠阻塞的情況,這種情況產生至少需要兩個以上的線程和兩個以上的資源。
分析死鎖,需要查看Java應用程序的線程轉儲,需要找出那些狀態為BLOCKED的線程和他們等待的資源。每個資源都有一個唯一的id,用這個id可以找出哪些線程已經擁有了它的對象鎖。
避免嵌套鎖,只在需要的地方使用鎖和避免無限期等待是避免死鎖的通常辦法。

㈡ java中死鎖的概念是什麼給個例子

packagelock;

{

privateStringlock1="lock1";//鎖1
privateStringlock2="lock2";//鎖2
privatebooleanflag=true;//執行標志

@Override
publicvoidrun(){

try{
if(flag){
flag=false;
step1:synchronized(lock1){//第一個線程查看lock1鎖旗標狀態,發現可用,為lock1設置鎖旗標後,開始執行任務。此時lock1已經被鎖。
System.out.println(Thread.currentThread().getName()+"開始執行第1個任務");
Thread.sleep(100);//睡眠等待,此時線程2在執行
step3:synchronized(lock2){//第一個線程查看lock2鎖旗標狀態,發現lock2被鎖定,等待。
System.out.println(Thread.currentThread().getName()+"開始執行第2個任務");
}
}
}else{
flag=true;
step2:synchronized(lock2){//第二個線程查看lock2鎖旗標狀態,發現可用,為lock2設置鎖旗標後,開始執行任務。此時lock2已經被鎖。
System.out.println(Thread.currentThread().getName()+"開始執行第1個任務");
Thread.sleep(100);////睡眠等待,此時線程1在執行
step4:synchronized(lock1){//第二個線程查看lock1鎖旗標狀態,發現lock1被鎖定,等待。
System.out.println(Thread.currentThread().getName()+"開始執行第2個任務");
}
}
}
}catch(InterruptedExceptione){
e.printStackTrace();
}
}

}


packagelock;

/**
*死鎖測試類
*@authorremind
*/
publicclassTest{

publicstaticvoidmain(String[]args){
//開啟兩個線程
Tasktask=newTask();
newThread(task,"線程1").start();
newThread(task,"線程2").start();
}
}

我在里邊加入了4個階段setp1、2、3、4。可以配合看一下。

死鎖原理:兩個線程,兩把鎖,同步執行。

1、線程1把鎖1的狀態設置為佔用(鎖旗標),然後查看鎖2狀態,發現鎖2狀態為被佔用,處於等待。

2、線程2把鎖2的狀態設置為佔用(鎖旗標),然後查看鎖1狀態,發現鎖1狀態為被佔用,處於等待。

兩個線程互相等待,線程1不釋放鎖1,等待鎖2。線程2不釋放鎖2,等待鎖1。死鎖形成。

㈢ Java 多線程中 什麼是死鎖有什麼作用

所謂死鎖:
是指兩個或兩個以上的進程在執行過程中,因爭奪資源而造成的一種互相等待的現象,若無外力作用,它們都將無法推進下去。此時稱系統處於死鎖狀態或系統產生了死鎖,這些永遠在互相等待的進程稱為死鎖進程。
由於資源佔用是互斥的,當某個進程提出申請資源後,使得有關進程在無外力協助下,永遠分配不到必需的資源而無法繼續運行,這就產生了一種特殊現象死鎖。

㈣ java多線程中的死鎖,活鎖,飢餓,無鎖都是什麼鬼

死鎖發生在當一些進程請求其它進程佔有的資源而被阻塞時。

另外一方面,活鎖不會被阻塞,而是不停檢測一個永遠不可能為真的條件。除去進程本身持有的資源外,活鎖狀態的進程會持續耗費寶貴的CPU時間。

最後,進程會處於飢餓狀態是因為持續地有其它優先順序更高的進程請求相同的資源。不像死鎖或者活鎖,飢餓能夠被解開。例如,當其它高優先順序的進程都終止時並且沒有更高優先順序的進程到達。

㈤ java的死鎖是什麼,如何避免死鎖

我們先看看這樣一個生活中的例子:在一條河上有一座橋,橋面較窄,只能容納一輛汽車通過,無法讓兩輛汽車並行。如果有兩輛汽車A和B分別由橋的兩端駛上該橋,則對於A車來說,它走過橋面左面的一段路(即佔有了橋的一部分資源),要想過橋還須等待B車讓出右邊的橋面,此時A車不能前進;對於B車來說,它走過橋面右邊的一段路(即佔有了橋的一部分資源),要想過橋還須等待A車讓出左邊的橋面,此時B車也不能前進。兩邊的車都不倒車,結果造成互相等待對方讓出橋面,但是誰也不讓路,就會無休止地等下去。這種現象就是死鎖。如果把汽車比做進程,橋面作為資源,那麽上述問題就描述為:進程A佔有資源R1,等待進程B佔有的資源Rr;進程B佔有資源Rr,等待進程A佔有的資源R1。而且資源R1和Rr只允許一個進程佔用,即:不允許兩個進程同時佔用。結果,兩個進程都不能繼續執行,若不採取其它措施,這種循環等待狀況會無限期持續下去,就發生了進程死鎖。
在計算機系統中,涉及軟體,硬體資源都可能發生死鎖。例如:系統中只有一台CD-ROM驅動器和一台列印機,某一個進程佔有了CD-ROM驅動器,又申請列印機;另一進程佔有了列印機,還申請CD-ROM。結果,兩個進程都被阻塞,永遠也不能自行解除。
所謂死鎖,是指多個進程循環等待它方佔有的資源而無限期地僵持下去的局面。很顯然,如果沒有外力的作用,那麽死鎖涉及到的各個進程都將永遠處於封鎖狀態。從上面的例子可以看出,計算機系統產生死鎖的根本原因就是資源有限且操作不當。即:一種原因是系統提供的資源太少了,遠不能滿足並發進程對資源的需求。這種競爭資源引起的死鎖是我們要討論的核心。例如:消息是一種臨時性資源。某一時刻,進程A等待進程B發來的消息,進程B等待進程C發來的消息,而進程C又等待進程A發來的消息。消息未到,A,B,C三個進程均無法向前推進,也會發生進程通信上的死鎖。另一種原因是由於進程推進順序不合適引發的死鎖。資源少也未必一定產生死鎖。就如同兩個人過獨木橋,如果兩個人都要先過,在獨木橋上僵持不肯後退,必然會應競爭資源產生死鎖;但是,如果兩個人上橋前先看一看有無對方的人在橋上,當無對方的人在橋上時自己才上橋,那麽問題就解決了。所以,如果程序設計得不合理,造成進程推進的順序不當,也會出現死鎖。

㈥ 如何理解Java中的死鎖

死鎖是這樣一種情形:多個線程同時被阻塞,它們中的一個或者全部都在等待某個資源被釋放。由於線程被無限期地阻塞,因此程序不可能正常終止。

導致死鎖的根源在於不適當地運用「synchronized」關鍵詞來管理線程對特定對象的訪問。「synchronized」關鍵詞的作用是,確保在某個時刻只有一個線程被允許執行特定的代碼塊,因此,被允許執行的線程首先必須擁有對變數或對象的排他性的訪問權。當線程訪問對象時,線程會給對象加鎖,而這個鎖導致其它也想訪問同一對象的線程被阻塞,直至第一個線程釋放它加在對象上的鎖。

由於這個原因,在使用「synchronized」關鍵詞時,很容易出現兩個線程互相等待對方做出某個動作的情形。代碼一是一個導致死鎖的簡單例子。

//代碼一
class Deadlocker {
int field_1;
private Object lock_1 = new int[1];
int field_2;
private Object lock_2 = new int[1];

public void method1(int value) {
「synchronized」 (lock_1) {
「synchronized」 (lock_2) {
field_1 = 0; field_2 = 0;
}
}
}

public void method2(int value) {
「synchronized」 (lock_2) {
「synchronized」 (lock_1) {
field_1 = 0; field_2 = 0;
}
}
}
}

參考代碼一,考慮下面的過程:

◆ 一個線程(ThreadA)調用method1()。

◆ ThreadA在lock_1上同步,但允許被搶先執行。

◆ 另一個線程(ThreadB)開始執行。

◆ ThreadB調用method2()。

◆ ThreadB獲得lock_2,繼續執行,企圖獲得lock_1。但ThreadB不能獲得lock_1,因為ThreadA佔有lock_1。

◆ 現在,ThreadB阻塞,因為它在等待ThreadA釋放lock_1。

◆ 現在輪到ThreadA繼續執行。ThreadA試圖獲得lock_2,但不能成功,因為lock_2已經被ThreadB佔有了。

◆ ThreadA和ThreadB都被阻塞,程序死鎖。

當然,大多數的死鎖不會這么顯而易見,需要仔細分析代碼才能看出,對於規模較大的多線程程序來說尤其如此。好的線程分析工具,例如JProbe Threadalyzer能夠分析死鎖並指出產生問題的代碼位置。

隱性死鎖

隱性死鎖由於不規范的編程方式引起,但不一定每次測試運行時都會出現程序死鎖的情形。由於這個原因,一些隱性死鎖可能要到應用正式發布之後才會被發現,因此它的危害性比普通死鎖更大。下面介紹兩種導致隱性死鎖的情況:加鎖次序和佔有並等待。

加鎖次序

當多個並發的線程分別試圖同時佔有兩個鎖時,會出現加鎖次序沖突的情形。如果一個線程佔有了另一個線程必需的鎖,就有可能出現死鎖。考慮下面的情形,ThreadA和ThreadB兩個線程分別需要同時擁有lock_1、lock_2兩個鎖,加鎖過程可能如下:

◆ ThreadA獲得lock_1;

◆ ThreadA被搶占,VM調度程序轉到ThreadB;

◆ ThreadB獲得lock_2;

◆ ThreadB被搶占,VM調度程序轉到ThreadA;

◆ ThreadA試圖獲得lock_2,但lock_2被ThreadB佔有,所以ThreadA阻塞;

◆ 調度程序轉到ThreadB;

◆ ThreadB試圖獲得lock_1,但lock_1被ThreadA佔有,所以ThreadB阻塞;

◆ ThreadA和ThreadB死鎖。

必須指出的是,在代碼絲毫不做變動的情況下,有些時候上述死鎖過程不會出現,VM調度程序可能讓其中一個線程同時獲得lock_1和lock_2兩個鎖,即線程獲取兩個鎖的過程沒有被中斷。在這種情形下,常規的死鎖檢測很難確定錯誤所在。

佔有並等待

如果一個線程獲得了一個鎖之後還要等待來自另一個線程的通知,可能出現另一種隱性死鎖,考慮代碼二。

//代碼二
public class queue {
static java.lang.Object queueLock_;
Procer procer_;
Consumer consumer_;

public class Procer {
void proce() {
while (!done) {
「synchronized」 (queueLock_) {
proceItemAndAddItToQueue();
「synchronized」 (consumer_) {
consumer_.notify();
}
}
}
}

public class Consumer {
consume() {
while (!done) {
「synchronized」 (queueLock_) {
「synchronized」 (consumer_) {
consumer_.wait();
}
();
}
}
}
}
}
}

在代碼二中,Procer向隊列加入一項新的內容後通知Consumer,以便它處理新的內容。問題在於,Consumer可能保持加在隊列上的鎖,阻止Procer訪問隊列,甚至在Consumer等待Procer的通知時也會繼續保持鎖。這樣,由於Procer不能向隊列添加新的內容,而Consumer卻在等待Procer加入新內容的通知,結果就導致了死鎖。

在等待時佔有的鎖是一種隱性的死鎖,這是因為事情可能按照比較理想的情況發展—Procer線程不需要被Consumer占據的鎖。盡管如此,除非有絕對可靠的理由肯定Procer線程永遠不需要該鎖,否則這種編程方式仍是不安全的。有時「佔有並等待」還可能引發一連串的線程等待,例如,線程A佔有線程B需要的鎖並等待,而線程B又佔有線程C需要的鎖並等待等。

要改正代碼二的錯誤,只需修改Consumer類,把wait()移出「synchronized」()即可。

㈦ 什麼是java多線程中的死鎖

一個進程在等待一個不可能發生的事,即進程死鎖,如果一個或多個進程產生死鎖,就會造成系統死鎖。
3、死鎖發生的必要條件
(1)、互斥條件:一個資源每次只能被一個進程使用,在操作系統中這是真實存在的情況。
(2)、保護和等待條件:有一個進程已獲得了一些資源,但因請求其他資源被阻塞時,對已獲得的資源保持不放。
(3)、不剝奪條件:有些系統資源是不可剝奪的,當某個進程已獲得這種資源後,系統不能強行收回,只能由進程使用完時自己釋放。
(4)、環路等待條件:若干個進程形成環行鏈,每個都佔用對方要申請的下一個資源。

㈧ java怎麼避免死鎖

解決方式:
1、盡量使用tryLock(long timeout, TimeUnit unit)的方法(ReentrantLock、ReentrantReadWriteLock),設置超時時間,超時可以退出防止死鎖。
2、盡量使用java.util.concurrent(jdk 1.5以上)包的並發類代替手寫控制並發,比較常用的是ConcurrentHashMap、ConcurrentLinkedQueue、AtomicBoolean等等,實際應用中java.util.concurrent.atomic十分有用,簡單方便且效率比使用Lock更高 。
3、盡量降低鎖的使用粒度,盡量不要幾個功能用同一把鎖 。
4、盡量減少同步的代碼塊。

㈨ JAVA中,線程死鎖是什麼意思

兩個或者多個線程之間相互等待,導致線程都無法執行,叫做線程死鎖。
產生死鎖的條件:
1.有至少一個資源不能共享
2.至少有一個任務必須持有一個資源並且等待獲取另一個被別的任務持有的資源
3.資源不能任務搶占
4.必須有循環等待
高淇Java300集視頻教程對線程死鎖有詳細的講解。

㈩ 如何避免Java多線程中的死鎖

死鎖產生的必要條件
產生死鎖必須同時滿足以下四個條件,只要其中任一條件不成立,死鎖就不會發生。
互斥條件:進程要求對所分配的資源(如列印機)進行排他性控制,即在一段時間內某 資源僅為一個進程所佔有。此時若有其他進程請求該資源,則請求進程只能等待。
不剝奪條件:進程所獲得的資源在未使用完畢之前,不能被其他進程強行奪走,即只能 由獲得該資源的進程自己來釋放(只能是主動釋放)。
請求和保持條件:進程已經保持了至少一個資源,但又提出了新的資源請求,而該資源 已被其他進程佔有,此時請求進程被阻塞,但對自己已獲得的資源保持不放。
循環等待條件:存在一種進程資源的循環等待鏈,鏈中每一個進程已獲得的資源同時被 鏈中下一個進程所請求。即存在一個處於等待狀態的進程集合{Pl, P2, ..., pn},其中Pi等 待的資源被P(i+1)佔有(i=0, 1, ..., n-1),Pn等待的資源被P0佔有

閱讀全文

與java中死鎖相關的資料

熱點內容
游俠下載的游戲都需要解壓沒 瀏覽:81
初次認識控制命令完整版 瀏覽:255
雙屏程序員 瀏覽:799
怎麼把兩個文件夾放到一個文件夾裡面 瀏覽:545
命令與征服大神宮 瀏覽:207
php發送簡訊驗證碼 瀏覽:505
前端伺服器如何接收http請求 瀏覽:796
程序員資質查詢 瀏覽:357
程序員被別人開除怎麼辦 瀏覽:888
解壓視頻看一下 瀏覽:129
android仿知乎日報 瀏覽:335
為什麼前端比安卓手機需求大 瀏覽:855
命令行執行關機命令 瀏覽:52
在學校心情不好怎麼解壓 瀏覽:116
我的世界基岩版伺服器怎麼讀取 瀏覽:161
快件命令 瀏覽:853
阿里雲06折伺服器能用嗎 瀏覽:421
h5個人中心源碼 瀏覽:221
下三角矩陣的壓縮存儲 瀏覽:922
招人用什麼app好用 瀏覽:722