一、死鎖的産生條件
- 互斥使用:一個資源隻能配置設定給一個線程
- 不可剝奪:資源隻能由占有者釋放,申請者不能強制剝奪
- 請求保持:線程申請資源時,保持對原有資源的占有
-
循環等待:存在一個程序等待隊列:{P1 , P2 , … , Pn}, 其中P1等待P2占有的資源,P2等待P3占有的資源,…,Pn等待P1占有的資源,形成一個程序等待環路
代碼
- 引用連結:https://www.jianshu.com/p/8cf78bf94f9d
二、死鎖代碼示例
自定義一個線程實作類,
package com.yunshi.synchronizedtest;
import org.hibernate.validator.internal.util.privilegedactions.NewInstance;
/**
*
死鎖條件
互斥使用:一個資源隻能配置設定給一個線程
不可剝奪:資源隻能由占有者釋放,申請者不能強制剝奪
請求保持:線程申請資源時,保持對原有資源的占有
循環等待:存在一個程序等待隊列:{P1 , P2 , … , Pn}, 其中P1等待P2占有的資源,P2等待P3占有的資源,…,Pn等待P1占有的資源,形成一個程序等待環路
代碼
思路
定義兩個資源o1,o2
對象deadLock1占有資源o1,需要資源o2
對象deadLock2占有資源o2,需要資源o1
死鎖産生
* @author Administrator
*
*/
public class DeadLock implements Runnable{
/**
* 定義兩個Object對象,模拟兩個線程占有的共享資源
* 此處需要注意的是,o1和o2 需要有static修飾,定義為靜态對象,這樣o1和o2才能在多個線程之間調用,才屬于共享資源,
* 沒有static修飾的話,DeadLock的每個執行個體對象中的 o1和o2 都将是獨立存在,互相隔離的,
*/
public static Object o1= new Object();
public static Object o2= new Object();
public int flag; // 屬性,又叫成員變量
public DeadLock(int flag) {
super();
this.flag = flag;
}
@Override
public void run() {
if (flag==1) {
// 代碼塊1
synchronized (o1) {
System.out.println("one-1");
try {
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
synchronized (o2) {
System.out.println("one-2");
}
}
}else {
// 代碼塊2
synchronized (o2) {
System.out.println("two-1");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (o1) {
System.out.println("two-2");
}
}
}
}
public static void main(String[] args) {
//建立線程1,flag 屬性值為1
DeadLock deadLock1 = new DeadLock(1);
//建立線程1,flag 屬性值為2
DeadLock deadLock2 = new DeadLock(2);
//啟動線程1和線程2
/**
* 線程1啟動之後,調用順序是
* (1)執行代碼塊1,同時擷取到o1對象鎖,開始執行,線程沉睡1秒
* (2)接着去擷取o2的對象鎖,由于第二個線程先擷取的是o2的對象鎖,是以需要等待代碼塊2執行完畢,才能擷取到o2的對象鎖
*/
new Thread(deadLock1).start();
/**
* 線程2啟動之後,調用順序是
* (1)執行代碼塊2,同時擷取到o2對象鎖,開始執行,線程沉睡1秒
* (2)接着去擷取o1的對象鎖,由于第一個線程先擷取的是o1的對象鎖,是以需要等待代碼塊1執行完畢,才能擷取到o1的對象鎖
*/
new Thread(deadLock2).start();
/** 以上分析可得,線程一和線程二共用了對象o1和o2,各自都想要擷取對方的鎖,進而形成阻塞,一直等待下去,這種現象就是死鎖。*/
}
}