死锁
多个线程同时被阻塞,它们中的⼀个或者全部都在等待某个资源被释放。由于线程被⽆限期地阻塞,因此程序不可能正常终⽌。
如下图所示,线程 A 持有资源 2,线程 B 持有资源 1,他们同时都想申请对⽅的资源,所以这两个线程就会互相等待⽽进⼊死锁状态。
示例:
public class DeadLockDemo {
private static Object lock1 = new Object();//锁1,资源1
private static Object lock2 = new Object();//锁2,资源2
public static void main(String[] args) {
//启动一个线程
new Thread(new Runnable() {
@Override
public void run() {
synchronized(lock1){
System.out.println(Thread.currentThread().getName()+"拿到了锁1,资源1");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"等待锁2,资源2");
synchronized (lock2){
System.out.println(Thread.currentThread().getName()+"拿到了锁2,资源2");
}
}
}
},"线程1").start();
//产生死锁的线程
new Thread(new Runnable() {
@Override
public void run() {
synchronized(lock1){
System.out.println(Thread.currentThread().getName()+"拿到了锁2,资源2");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"等待锁1,资源1");
synchronized (lock2){
System.out.println(Thread.currentThread().getName()+"拿到了锁1,资源1");
}
}
}
},"线程2").start();
}
}
线程 A 通过 synchronized (resource1) 获得 resource1 的监视器锁,然后通过Thread.sleep(1000); 让线程 A 休眠 1s 为的是让线程 B 得到执⾏然后获取到 resource2 的监视器锁。线程 A 和线程 B 休眠结束了都开始企图请求获取对⽅的资源,然后这两个线程就会陷⼊互相等待的状态,这也就产⽣了死锁。
破坏死锁
//破坏死锁
new Thread(new Runnable() {
@Override
public void run() {
synchronized(lock1){
System.out.println(Thread.currentThread().getName()+"拿到了锁1,资源1");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"等待 锁2,资源2");
synchronized (lock2){
System.out.println(Thread.currentThread().getName()+"拿到了锁2,资源2");
}
}
}
},"线程2").start();
线程 1 ⾸先获得到 resource1 的监视器锁,这时候线程 2 就获取不到了。然后线程 1 再去获取resource2 的监视器锁,可以获取到。然后线程 1 释放了对 resource1、resource2 的监视器锁的占⽤,线程 2 获取到就可以执⾏了。这样就破坏了破坏循环等待条件,因此避免了死锁。