A. 如何避免java多線程中的死鎖
死鎖產生的必要條件
產生死鎖必須同時滿足以下四個條件,只要其中任一條件不成立,死鎖就不會發生。
互斥條件:進程要求對所分配的資源(如列印機)進行排他性控制,即在一段時間內某 資源僅為一個進程所佔有。此時若有其他進程請求該資源,則請求進程只能等待。
不剝奪條件:進程所獲得的資源在未使用完畢之前,不能被其他進程強行奪走,即只能 由獲得該資源的進程自己來釋放(只能是主動釋放)。
請求和保持條件:進程已經保持了至少一個資源,但又提出了新的資源請求,而該資源 已被其他進程佔有,此時請求進程被阻塞,但對自己已獲得的資源保持不放。
循環等待條件:存在一種進程資源的循環等待鏈,鏈中每一個進程已獲得的資源同時被 鏈中下一個進程所請求。即存在一個處於等待狀態的進程集合{Pl, P2, ..., pn},其中Pi等 待的資源被P(i+1)佔有(i=0, 1, ..., n-1),Pn等待的資源被P0佔有
B. java多線程死鎖問題
public class Test520 {//測試類
public static void main(String[] args) {
Test1 t1=new Test1();//構造線程1
Test2 t2=new Test2();//構造線程2
t1.start();//啟動線程1
t2.start();//啟動線程2
}
}
class Test1 extends Thread{//線程類1
public void run() {//線程類1的run方法
synchronized (A.class) {//線程類1獲取A類的鎖
new A().a();//構建A類調用a方法,線程可以執行到這里
synchronized (B.class) {//線程1請求獲取B類的鎖,看後面的代碼我們知道B類的鎖在線程2中,形成死鎖
new B().b();//構造B類,調用b方法,這語句無法執行,因線程1始終無法獲得已被線程2獲得的B類鎖
}
}
}
}
class Test2 extends Thread{//線程類2
public void run() {//線程類2的run方法
synchronized (B.class) {//線程2獲取了B類的鎖,因此線程1無法在調用a方法後獲取B類鎖執行後面的語句
new A().a();//構造A類對象調用a方法,此語句可以執行
synchronized (A.class) {//線程2請求A類鎖,A類鎖此時被線程1持有
new B().b();//如果線程2能夠獲取A類鎖,就能執行這一步,測試知道,無法執行到這句
}
}
}
}
class A{//測試類
public void a() {
System.out.println("a");
}
}
class B{//測試類
public void b() {
System.out.println("b");
}
}
C. 怎麼處理JAVA多線程死鎖問題
有兩種實現方法,分別是繼承Thread類與實現Runnable 介面
用synchronized關鍵字修飾同步方法
反對使用stop(),是因為它不安全。它會解除由線程獲取的所有鎖定,而且如果對象處於一種不連貫狀態,那麼
其他線程能在那種狀態下檢查和修改它們。結果很難檢查出真正的問題所在。suspend()方法容易發生死鎖。調用
suspend()的時候,目標線程會停下來,但卻仍然持有在這之前獲得的鎖定。此時,其他任何線程都不能訪問鎖定
的資源,除非被"掛起"的線程恢復運行。對任何線程來說,如果它們想恢復目標線程,同時又試圖使用任何一個
鎖定的資源,就會造成死鎖。所以不應該使用suspend(),而應在自己的Thread類中置入一個標志,指出線程應該
活動還是掛起。若標志指出線程應該掛起,便用wait()命其進入等待狀態。若標志指出線程應當恢復,則用一個
notify()重新啟動線程。
D. 求解java多線程的死鎖
你這是同步鎖,鎖的是A對象。有線程跟你一樣用 A對象當鎖的時候 ,只會有一條線程 來執行 B。其他線程都得等待。
1.A區域究竟什麼對象可以作為鎖?
對象,類對象。類對象 全局只有一個 比如 A.class ,當有人用到 這個類對象的時候 就會將其鎖住。不讓其他線程進入。
2.是不是我在一個線程中將A這個對象作為鎖,在另一個線程中對A這個對象進行操作,就會發生死鎖?
死鎖的根本原因1)是多個線程涉及到多個鎖,這些鎖存在著交叉,所以可能會導致了一個鎖依賴的閉環;2)默認的鎖申請操作是阻塞的。所以要避免死鎖,就要在一遇到多個對象鎖交叉的情況,就要仔細審查這幾個對象的類中的所有方法,是否存在著導致鎖依賴的環路的可能性。要採取各種方法來杜絕這種可能性。
你這樣 鎖不到的。舉個例子 死鎖 就是 x線程 鎖住了 A對象 然後 調用B對象的方法,y線程 鎖住了B對象調用A對象的方法,兩邊 都在互相嘗試獲取對方的鎖,但是拿不到。因為 x鎖住了A對象。y鎖住了B對象。他們互相拿不到 就叫死鎖。這只是個例子還有很多。
3不是說任何對象都可以作為一把鎖嗎?那麼每一個鎖我使用一個獨立的成員對象作為鎖,不就是可以很容易避開死鎖嗎?為什麼說死鎖很容易發生?
你每個鎖用一個獨立的成員對象作為鎖,沒問題,只要沒有存在交叉。上面那個例子一樣。
避免死鎖是一件困難的事,遵循以下原則有助於規避死鎖:
1、只在必要的最短時間內持有鎖,考慮使用同步語句塊代替整個同步方法;
2、盡量編寫不在同一時刻需要持有多個鎖的代碼,如果不可避免,則確保線程持有第二個鎖的時間盡量短暫;
3、創建和使用一個大鎖來代替若干小鎖,並把這個鎖用於互斥,而不是用作單個對象的對象級別鎖;
E. 如何解決多線程造成的資料庫死鎖
多線程是很容易造成死鎖,一般情況下死鎖都是因為並發操作引起的。我不懂JAVA,但死鎖這個問題每種開發工具和資料庫都會碰到.解決辦法是:
1、程序方面優化演算法(如有序資源分配法、銀行演算法等),在一個程序里,能不用多線程更新同一張資料庫表
盡量不要用,如果要用,其避免死鎖的演算法就很復雜。
2、資料庫方面設置等待超時時間
3、發生死鎖後直接KILL掉資料庫進程
F. 什麼是java多線程中的死鎖
兩個或者多個線程之間相互等待,導致線程都無法執行,叫做線程死鎖。
產生死鎖的條件:
1.有至少一個資源不能共享
2.至少有一個任務必須持有一個資源並且等待獲取另一個被別的任務持有的資源
3.資源不能任務搶占
4.必須有循環等待
G. 如何理解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」()即可。
H. java多線程中的死鎖,活鎖,飢餓,無鎖都是什麼鬼
死鎖發生在當一些進程請求其它進程佔有的資源而被阻塞時。
另外一方面,活鎖不會被阻塞,而是不停檢測一個永遠不可能為真的條件。除去進程本身持有的資源外,活鎖狀態的進程會持續耗費寶貴的CPU時間。
最後,進程會處於飢餓狀態是因為持續地有其它優先順序更高的進程請求相同的資源。不像死鎖或者活鎖,飢餓能夠被解開。例如,當其它高優先順序的進程都終止時並且沒有更高優先順序的進程到達。
I. Java 多線程中 什麼是死鎖有什麼作用
所謂死鎖:
是指兩個或兩個以上的進程在執行過程中,因爭奪資源而造成的一種互相等待的現象,若無外力作用,它們都將無法推進下去。此時稱系統處於死鎖狀態或系統產生了死鎖,這些永遠在互相等待的進程稱為死鎖進程。
由於資源佔用是互斥的,當某個進程提出申請資源後,使得有關進程在無外力協助下,永遠分配不到必需的資源而無法繼續運行,這就產生了一種特殊現象死鎖。