什么是死锁
多个进程或者线程同时被被阻塞,他们中的一个或者全部都在等待某个资源的释放。但是由于进程或者线程被无限期的阻塞,导致程序不能正常终止。
产生死锁的四个必要条件
- 互斥:资源必须处于非共享模式,即一次只能由一个线程可以使用,如果另一线程申请资源,就必须等待直到该资源被释放为止。
- 占有并等待:一个进程应该至少占用一个资源,并等待另一资源,但是该资源被其他线程所占用。
- 非抢占:资源不能被抢占。只能在持有资源的线程完成任务后,该资源才会被释放。
- 循环等待:有一组等待进程 ${P_0,P_1,...,P_n}$ ,$P_0$ 等待的资源被 $P_1$占用,$P_1$ 等待的资源被 $P_2$占用,一次类推,形成了一个环。
锁顺序死锁
线程 1 拿到 A锁 后 又去拿 B锁,线程 2 拿到 B锁 后 又去拿 A锁
导致线程 1 拿B锁的时候,B锁被 线程 2 拿着,线程1阻塞
线程 2 拿A锁的时候,A锁 被 线程 1 拿着,线程2阻塞
最终两个线程谁也拿不到,使得两个线程都开始阻塞
public void test2() throws InterruptedException {
Object lock = new Object();
Object lockA = new Object();
Object lockB = new Object();
Thread thread1 = new Thread(()->{
synchronized (lockA){
System.out.println(Thread.currentThread().getName() +"获取 A" );
try{
Thread.sleep(100);
}catch (Exception e){
e.printStackTrace();
}
synchronized (lockB){
System.out.println(Thread.currentThread().getName() +"获取 B" );
}
}
},"线程1");
Thread thread2 = new Thread(()->{
synchronized (lockB){
System.out.println(Thread.currentThread().getName() +"获取 B" );
try{
Thread.sleep(100);
}catch (Exception e){
e.printStackTrace();
}
synchronized (lockA){
System.out.println(Thread.currentThread().getName() +"获取 A" );
}
}
},"线程2");
thread1.start();
thread2.start();
thread1.join();
thread2.join();
}
不可重入锁 造成的死锁
对于不可重入锁,如果在一个线程里重复地获取它,就会造成死锁,因为使用该锁需要等待当前线程释放锁,但想要释放锁就必须要获取锁,造成阻塞。
public void test2() throws InterruptedException {
NonReentrantLock lock1 = new NonReentrantLock();
Thread thread1 = new Thread(()->{
try {
lock1.lock();
System.out.println(Thread.currentThread().getName() +"获取 A" );
try{
lock1.lock();
System.out.println(Thread.currentThread().getName() +"获取 A+" );
}catch (Exception e){
e.printStackTrace();
}finally {
lock1.unlock();
}
} catch (InterruptedException e) {
throw new RuntimeException(e);
}finally {
lock1.unlock();
}
},"线程1");
thread1.start();
thread1.join();
}
package utils;
/**
* @Date 2025-11-23 23:08
* @Author ouyu
* @Description
**/
public class NonReentrantLock {
private boolean isLocked = false;
public synchronized void lock() throws InterruptedException {
while (isLocked) {
wait(); // 如果锁已被持有,当前线程等待
}
isLocked = true; // 获取锁
}
public synchronized void unlock() {
isLocked = false; // 释放锁
notify(); // 唤醒等待的线程
}
}

Comments NOTHING