要想实现线程死锁,首先要清楚线程死锁的四个条件
- 互斥条件:一个资源每次只能被一个进程使用,即在一段时间内某资源仅为一个进程所使用。此时如果有其它进程请求该资源,则请求进程只能等待。
- 请求和保持条件:进程中已经保持了至少一个资源,但又提出了新的资源请求,而该资源已经被其它进程占用,此时请求进程被阻塞,但对它自己已经获得的资源保持不放。
- 不可剥夺条件:进程未使用完的资源在未使用完毕之前,不能被其它进程强行夺走,即只能由获得该资源的进程自己来释放
- 循环等待条件:若干进程间形成首尾相接循环等待资源的关系。在发生死锁时必然存在一个进程等待列队{P1, P2, ..., Pn},其中P1等待P2占有的资源,P2等待P3占有的资源....,Pn等待P1占有的资源。形成一个进程等待环路,环路中每一个进程所占有的资源同时被同一个申请。
class MyThread extends Thread{
//类属性被所有实例共享
static Object o1 = new Object();
static Object o2 = new Object();
public MyThread(int flag){
this.flag = flag;
}
@Override
public void run(){
if(flag == 0){
// 若flag==0 锁住o1
synchronized(o1){
System.out.println(flag + "锁住了o1");
// 线程睡眠,让出cpu,但不释放锁
Thread.sleep(1000);
// 请求锁对象o2,但o2被flag==1占用
synchronized(o2){
System.out.println(flag + "锁住了o2");
}
}
// 线程死锁,无法继续执行
System.out.println(flag + "释放了o1和o2");
}
if(flag == 1){
// 若flag==1 锁住o2
synchronized(o2){
System.out.println(flag + "锁住了o2");
// 线程睡眠,让出cpu,但不释放锁
Thread.sleep(1000);
// 请求锁对象o1,但o1被flag==0占用
synchronized(o1){
System.out.println(flag + "锁住了o1");
}
// 线程死锁,无法继续执行
System.out.println(flag + "释放了o1和o2");
}
}
}
}
public class ThreadDeadLock{
public static void main(String[] args){
MyThread t1 = new MyThread(0);
MyThread t2 = new MyThread(1);
t1.start();
t2.start();
}
}