死锁的定义:
- 两个或多个线程互相持有对方所需的资源,这些线程会互相等待对方释放资源,如果线程都不主动释放所占有的资源,这些线程都会处于等待状态,无法继续执行,产生死锁
死锁产生的条件:
- 互斥条件:线程对所分配的资源具有排他性,即一个资源只能被一个线程占用,直到该线程释放该资源;
- 请求和保持条件:一个线程因请求被占用资源而发生阻塞时,对已获得的资源保持不放;
- 不剥夺条件:任何一个备战有的资源在没被该线程释放之前,任何其他线程都无法对他进行剥夺占用;
- 循环等待条件:当发生死锁时,所等待的线程必定会形成一个死循环,造成永久阻塞。
死锁举例:
- 线程1首先占有对象1,接着试图占有对象2
- 线程2首先占有对象2,接着试图占有对象1
- 线程1等待线程2释放对象2
- 线程2等待线程1释放对象1
- 线程1和线程2形成死循环,死锁产生
代码展示
public class DeadLock {
//演示死锁
public static void main(String[] args) {
//创建两个对象->对象1和对象2
final Object o1 = new Object();
final Object o2 = new Object();
//创建线程1:首先占有对象1,接着试图占有对象2
Thread t1 = new Thread(){
public void run(){
//首先占有对象1
synchronized (o1) {
System.out.println( "t1已经占有对象o1" );
try {
//提供足够的时间让线程2占有对象o2
Thread.sleep( 10000 );
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//接着试图占有对象2
System.out.println( "t1试图占有对象o2" );
System.out.println( "t1等待中" );
synchronized ( o2 ) {
System.out.println( "do something" );
}
}
}
};
t1.start();
//创建线程2:首先占用对象2,接着试图占用对象1
Thread t2 = new Thread(){
public void run(){
//首先占有对象o2
System.out.println( "t2已经占用对象o2" );
synchronized (o2) {
try {
//提供足够的时间让线程1占有对象o1
Thread.sleep( 10000 );
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//接着试图占用对象o1
System.out.println( "t2试图占用对象o1" );
System.out.println( "t2等待中" );
synchronized (o1) {
System.out.println( "do something" );
}
}
}
};
t2.start();
}
}
输出结果
t1已经占有对象o1
t2已经占用对象o2
t2试图占用对象o1
t2等待中
t1试图占有对象o2
t1等待中
PS:2020年11月12日网易有道后台开发实习面试题