编写一段代码,使其必定产生死锁

打印 上一主题 下一主题

主题 2000|帖子 2000|积分 6004

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
编写一段代码,使得这段代码必定会产生死锁
利用Thread.sleep

以下是一个经典的 Java 死锁实现,通过两个线程互相持有对方需要的锁来确保必定发生死锁:
  1. public class DeadlockDemo {
  2.     // 创建两个锁对象
  3.     private static final Object lock1 = new Object();
  4.     private static final Object lock2 = new Object();
  5.    
  6.     public static void main(String[] args) {
  7.         // 线程1:先获取lock1,再尝试获取lock2
  8.         Thread thread1 = new Thread(() -> {
  9.             synchronized (lock1) {
  10.                 System.out.println("线程1持有lock1,等待lock2...");
  11.                 try {
  12.                     Thread.sleep(10000); // 等个10秒增加死锁概率
  13.                 } catch (InterruptedException e) {
  14.                     e.printStackTrace();
  15.                 }
  16.                 synchronized (lock2) {
  17.                     System.out.println("线程1成功获取lock2");
  18.                 }
  19.             }
  20.         });
  21.         // 线程2:先获取lock2,再尝试获取lock1
  22.         Thread thread2 = new Thread(() -> {
  23.             synchronized (lock2) {
  24.                 System.out.println("线程2持有lock2,等待lock1...");
  25.                 try {
  26.                     Thread.sleep(10000); // 等个10秒增加死锁概率
  27.                 } catch (InterruptedException e) {
  28.                     e.printStackTrace();
  29.                 }
  30.                 synchronized (lock1) {
  31.                     System.out.println("线程2成功获取lock1");
  32.                 }
  33.             }
  34.         });
  35.         
  36.         thread1.start();
  37.         thread2.start();
  38.         try {
  39.             thread1.join();
  40.             thread2.join();
  41.         } catch (InterruptedException e) {
  42.             e.printStackTrace();
  43.         }
  44.         
  45.         System.out.println("程序正常结束(这行永远不会执行)");
  46.     }
  47. }
复制代码
倒霉用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 持有了它
  • 由于互相称候对方释放锁,因此死锁发生
  1. import java.util.concurrent.CountDownLatch;
  2. public class GuaranteedDeadlock {
  3.     private static final Object lock1 = new Object();
  4.     private static final Object lock2 = new Object();
  5.     private static final CountDownLatch latch = new CountDownLatch(2);
  6.     public static void main(String[] args) {
  7.         Thread thread1 = new Thread(() -> {
  8.             synchronized (lock1) {
  9.                 System.out.println("Thread 1: Holding lock1...");
  10.                 latch.countDown(); // 让 thread2 也开始执行
  11.                
  12.                 try {
  13.                         latch.await(); // 保证两个线程同时竞争
  14.                 } catch (InterruptedException e) {
  15.                         e.printStackTrace();
  16.                 }
  17.                 synchronized (lock2) {
  18.                     System.out.println("Thread 1: Acquired lock2!");
  19.                 }
  20.             }
  21.         });
  22.         Thread thread2 = new Thread(() -> {
  23.             synchronized (lock2) {
  24.                 System.out.println("Thread 2: Holding lock2...");
  25.                 latch.countDown(); // 让 thread1 也开始执行
  26.                
  27.                 try {
  28.                         latch.await(); // 保证两个线程同时竞争
  29.                 } catch (InterruptedException e) {
  30.                         e.printStackTrace();
  31.                     }
  32.                    
  33.                 synchronized (lock1) {
  34.                     System.out.println("Thread 2: Acquired lock1!");
  35.                 }
  36.             }
  37.         });
  38.         thread1.start();
  39.         thread2.start();
  40.     }
  41. }
复制代码
除此之外,也可以利用CycliBarrier
错误树模
  1. public class DeadlockExample {
  2.     private static final Object lock1 = new Object();
  3.     private static final Object lock2 = new Object();
  4.     public static void main(String[] args) {
  5.         Thread thread1 = new Thread(() -> {
  6.             synchronized (lock1) {
  7.                 System.out.println("Thread 1: Holding lock1...");
  8.                
  9.                 // 试图获取 lock2
  10.                 synchronized (lock2) {
  11.                     System.out.println("Thread 1: Acquired lock2!");
  12.                 }
  13.             }
  14.         });
  15.         Thread thread2 = new Thread(() -> {
  16.             synchronized (lock2) {
  17.                 System.out.println("Thread 2: Holding lock2...");
  18.                
  19.                 // 试图获取 lock1(但 lock1 此时被 Thread1 持有)
  20.                 synchronized (lock1) {
  21.                     System.out.println("Thread 2: Acquired lock1!");
  22.                 }
  23.             }
  24.         });
  25.         thread1.start();
  26.         thread2.start();
  27.     }
  28. }
复制代码
上述的代码无法保证死锁,由于Java 的线程调度是由操作系统决定的,线程的实行顺序是不可预测的,thread1 大概会在 thread2 运行前快速获取 lock1 和lock2,然后释放它们,从而避免死锁
所以这段代码死锁的发生概率不是 100%。这也是为什么第一种方式要利用Thread.sleep来保证两个线程都分别得到了锁

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

王國慶

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表