仰景 發表於 2025-5-7 09:15:00

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

<p>编写一段代码,使得这段代码必定会产生死锁</p>
<h2 id="使用threadsleep">使用Thread.sleep</h2>
<p>以下是一个经典的 Java 死锁实现,通过两个线程互相持有对方需要的锁来确保必定发生死锁:</p>
<pre><code class="language-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(() -&gt; {
            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(() -&gt; {
            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("程序正常结束(这行永远不会执行)");
    }
}
</code></pre>
<h2 id="不使用threadsleep">不使用Thread.sleep</h2>
<p>可以使用 countDownLatch 来实现死锁,思路为:</p>
<ol>
<li>新建一个count为2的 CountDownLatch 对象 latch。</li>
<li>thread1 持有 lock1 后,调用 latch.countDown() 将计数减一,随后调用 latch.await() 等待,直到 thread2 也持有 lock2 后调用 latch.countDownd()</li>
<li>thread2 持有 lock2 后,调用 latch.countDown()将计数减一,随后调用 latch.await() 直到 thread1 调用 latch.countDown()</li>
<li>thread1 想要 lock2,但 thread2 持有了它</li>
<li>thread2 想要 lock1,但 thread1 持有了它</li>
<li>由于互相等待对方释放锁,因此死锁发生</li>
</ol>
<pre><code class="language-java">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(() -&gt; {
            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(() -&gt; {
            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();
    }
}
</code></pre>
<p>除此之外,也可以使用CycliBarrier</p>
<h2 id="错误示范">错误示范</h2>
<pre><code class="language-java">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(() -&gt; {
            synchronized (lock1) {
                System.out.println("Thread 1: Holding lock1...");
               
                // 试图获取 lock2
                synchronized (lock2) {
                  System.out.println("Thread 1: Acquired lock2!");
                }
            }
      });

      Thread thread2 = new Thread(() -&gt; {
            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();
    }
}
</code></pre>
<p>上述的代码无法保证死锁,因为Java 的线程调度是由操作系统决定的,线程的执行顺序是不可预测的,thread1 可能会在 thread2 运行前快速获取 lock1 和lock2,然后释放它们,从而避免死锁</p>
<p>所以这段代码死锁的发生概率不是 100%。这也是为什么第一种方式要使用Thread.sleep来保证两个线程都分别获得了锁</p>


</div>
<div id="MySignature" role="contentinfo">
    <p>本文来自在线网站:seven的菜鸟成长之路,作者:seven,转载请注明原文链接:www.seven97.top</p><br><br>
来源:https://www.cnblogs.com/sevencoding/p/18860312
頁: [1]
查看完整版本: 编写一段代码,使其必定产生死锁