死锁发生的原因:
1、系统资源有限
2、进程或线程推进顺序不恰当
3、资源分配不当
死锁发生的四个条件:
1、互斥条件:一份资源每次只能被一个进程或线程使用(在Java中一般体现为,一个对象锁只能被一个线程持有)
2、请求与保持条件:一个进程或线程在等待请求资源被释放时,不释放已占有资源
3、不可剥夺条件:一个进程或线程已经获得的资源不能被其他进程或线程强行剥夺
4、循环等待条件:形成一种循环等待的场景
下面看代码:
public class A {
public synchronized void waitMethod(B b) throws InterruptedException{
System.out.println(Thread.currentThread().getName() + ":正在执行a的等待方法,持有a的对象锁");
Thread.sleep(2000L);
System.out.println(Thread.currentThread().getName() + ":试图调用b的死锁方法,尝试获取b的对象锁");
b.deadLockMethod();
}
public synchronized void deadLockMethod(){
System.out.println(Thread.currentThread().getName() + ":正在执行a的死锁方法,持有a的对象锁");
}
}
public class B {
public synchronized void waitMethod(A a) throws InterruptedException{
System.out.println(Thread.currentThread().getName() + ":正在执行b的等待方法,持有b的对象锁");
Thread.sleep(2000L);
System.out.println(Thread.currentThread().getName() + ":试图调用a的死锁方法,尝试获取a的对象锁");
a.deadLockMethod();
}
public synchronized void deadLockMethod(){
System.out.println(Thread.currentThread().getName() + ":正在执行B的死锁方法,持有B的对象锁");
}
}
public class TestDeadLock implements Runnable {
A a = new A();
B b = new B();
public void init() throws InterruptedException{
Thread.currentThread().setName("主线程");
a.waitMethod(b);
}
@Override
public void run() {
Thread.currentThread().setName("副线程");
try {
b.waitMethod(a);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws InterruptedException{
TestDeadLock testDeadLock = new TestDeadLock();
Thread thread = new Thread(testDeadLock);
thread.start();
testDeadLock.init();
}
}
通过sleep()方法,可以实现主线程持有a的对象锁并请求b的对象锁、 副线程持有b的对象锁并请求a的对象锁的场景,即发生死锁。
效果如下: