package lock;
public class Task implements Runnable{
private String lock1 = "lock1"; // 锁1
private String lock2 = "lock2"; // 锁2
private boolean flag = true; // 执行标志
@Override
public void run() {
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 (InterruptedException e) {
e.printStackTrace();
}
}
}
package lock;
/**
* 死锁测试类
* @author remind
*/
public class Test {
public static void main(String[] args) {
//开启两个线程
Task task = new Task();
new Thread(task,"线程1").start();
new Thread(task,"线程2").start();
}
}
我在里边加入了4个阶段setp1、2、3、4。可以配合看一下。
死锁原理:两个线程,两把锁,同步执行。
1、线程1把锁1的状态设置为占用(锁旗标),然后查看锁2状态,发现锁2状态为被占用,处于等待。
2、线程2把锁2的状态设置为占用(锁旗标),然后查看锁1状态,发现锁1状态为被占用,处于等待。
两个线程互相等待,线程1不释放锁1,等待锁2。线程2不释放锁2,等待锁1。死锁形成。
用一句的简单话来概括就是:T1事务等待T2事务释放独占锁后才能完成某一项操作,而此时T2也同样需要等待T1事务释放独占锁才能完成某一项操作。这样就形成一个互相等待局面,那么此时DBMS判定死锁。