死锁产生有四个必要的条件:
(1) 互斥条件:一个资源每次只能被一个进程使用。
(2) 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
(3) 不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。
(4) 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
A.Java:
public class A {
//synchronized方法使用当前对象为锁 ----this Deadlock中A
synchronized void foo(B b) {
//主线程
String name = Thread.currentThread().getName();
System.out.println(name + " 进入 A.foo ");
try {
Thread.sleep(1000);
} catch (Exception e) {
System.out.println(e.getMessage());
}
System.out.println(name + " 尝试调用 B.last()");
b.last();//要想进入b.last();必须持有B对象锁
}
//如果在其他的类中创建A的对象并且调用A的last方法,则必须要A的锁
synchronized void last() {
System.out.println("inside A.last");
}
}
B.java:
public class B {
//synchronized方法使用当前对象为锁 ----this Deadlock中的B
synchronized void bar(A a)
{
//子线程
String name=Thread.currentThread().getName();
System.out.println(name + " 进入 B.bar");
try {
Thread.sleep(1000);
} catch(Exception e) {
System.out.println(e.getMessage());
}
System.out.println(name + " 尝试调用 A.last()");
a.last(); //要想进入a.last();必须持有A对象锁
}
//
synchronized void last()
{
System.out.println("inside A.last");
}
}
Deadlock.java
public class Deadlock implements Runnable {
A a = new A();
B b = new B();
Deadlock() {
Thread.currentThread().setName("主线程");
new Thread(this).start();
//1
a.foo(b); // get lock on a in this thread.
//a.foo(new B());
System.out.println("back in main thread");
}
public void run() {
Thread.currentThread().setName("子线程");
b.bar(a); // get lock on a in other thread.
//b.bar(new A());
System.out.println("back in other thread");
}
public static void main(String[] args) {
new Deadlock();
}
}
我们可以看到。A中用自己的同步方法,所以它持有自己的锁,同时在同步方法中它又b.last()请求B持有的锁;B也一样,持有自己的锁,同时请求A的锁,两者形成死锁。
解决方法,删掉A或者B的同步锁synchronized。