qidao123.com技术社区-IT企服评测·应用市场
标题:
编写一段代码,使其必定产生死锁
[打印本页]
作者:
王國慶
时间:
2025-5-7 09:39
标题:
编写一段代码,使其必定产生死锁
编写一段代码,使得这段代码必定会产生死锁
利用Thread.sleep
以下是一个经典的 Java 死锁实现,通过两个线程互相持有对方需要的锁来确保必定发生死锁:
public class DeadlockDemo {
// 创建两个锁对象
private static final Object lock1 = new Object();
private static final Object lock2 = new Object();
public static void main(String[] args) {
// 线程1:先获取lock1,再尝试获取lock2
Thread thread1 = new Thread(() -> {
synchronized (lock1) {
System.out.println("线程1持有lock1,等待lock2...");
try {
Thread.sleep(10000); // 等个10秒增加死锁概率
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lock2) {
System.out.println("线程1成功获取lock2");
}
}
});
// 线程2:先获取lock2,再尝试获取lock1
Thread thread2 = new Thread(() -> {
synchronized (lock2) {
System.out.println("线程2持有lock2,等待lock1...");
try {
Thread.sleep(10000); // 等个10秒增加死锁概率
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lock1) {
System.out.println("线程2成功获取lock1");
}
}
});
thread1.start();
thread2.start();
try {
thread1.join();
thread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("程序正常结束(这行永远不会执行)");
}
}
复制代码
倒霉用Thread.sleep
可以利用
countDownLatch
来实现死锁,思路为:
新建一个count为2的 CountDownLatch 对象 latch。
thread1 持有 lock1 后,调用 latch.countDown() 将计数减一,随后调用 latch.await() 等候,直到 thread2 也持有 lock2 后调用 latch.countDownd()
thread2 持有 lock2 后,调用 latch.countDown()将计数减一,随后调用 latch.await() 直到 thread1 调用 latch.countDown()
thread1 想要 lock2,但 thread2 持有了它
thread2 想要 lock1,但 thread1 持有了它
由于互相称候对方释放锁,因此死锁发生
import java.util.concurrent.CountDownLatch;
public class GuaranteedDeadlock {
private static final Object lock1 = new Object();
private static final Object lock2 = new Object();
private static final CountDownLatch latch = new CountDownLatch(2);
public static void main(String[] args) {
Thread thread1 = new Thread(() -> {
synchronized (lock1) {
System.out.println("Thread 1: Holding lock1...");
latch.countDown(); // 让 thread2 也开始执行
try {
latch.await(); // 保证两个线程同时竞争
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lock2) {
System.out.println("Thread 1: Acquired lock2!");
}
}
});
Thread thread2 = new Thread(() -> {
synchronized (lock2) {
System.out.println("Thread 2: Holding lock2...");
latch.countDown(); // 让 thread1 也开始执行
try {
latch.await(); // 保证两个线程同时竞争
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lock1) {
System.out.println("Thread 2: Acquired lock1!");
}
}
});
thread1.start();
thread2.start();
}
}
复制代码
除此之外,也可以利用
CycliBarrier
错误树模
public class DeadlockExample {
private static final Object lock1 = new Object();
private static final Object lock2 = new Object();
public static void main(String[] args) {
Thread thread1 = new Thread(() -> {
synchronized (lock1) {
System.out.println("Thread 1: Holding lock1...");
// 试图获取 lock2
synchronized (lock2) {
System.out.println("Thread 1: Acquired lock2!");
}
}
});
Thread thread2 = new Thread(() -> {
synchronized (lock2) {
System.out.println("Thread 2: Holding lock2...");
// 试图获取 lock1(但 lock1 此时被 Thread1 持有)
synchronized (lock1) {
System.out.println("Thread 2: Acquired lock1!");
}
}
});
thread1.start();
thread2.start();
}
}
复制代码
上述的代码无法保证死锁,由于Java 的线程调度是由操作系统决定的,线程的实行顺序是不可预测的,thread1 大概会在 thread2 运行前快速获取 lock1 和lock2,然后释放它们,从而避免死锁
所以这段代码死锁的发生概率不是 100%。这也是为什么第一种方式要利用Thread.sleep来保证两个线程都分别得到了锁
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
欢迎光临 qidao123.com技术社区-IT企服评测·应用市场 (https://dis.qidao123.com/)
Powered by Discuz! X3.4