无涯教程-Java - 处理线程死锁函数

28 阅读2分钟

死锁描述了一种情况,其中两个或多个线程永远被阻塞,互相等待,当多个线程需要相同的锁但以不同的顺序获得它们时,就会发生死锁。 Java多线程程序可能会遇到死锁情况,因为 synchronized 关键字会导致正在执行的线程在等待与指定对象关联的锁时被阻塞。这是一个示例。

public class TestThread {
   public static Object Lock1 = new Object();
   public static Object Lock2 = new Object();

public static void main(String args[]) { ThreadDemo1 T1 = new ThreadDemo1(); ThreadDemo2 T2 = new ThreadDemo2(); T1.start(); T2.start(); }

private static class ThreadDemo1 extends Thread { public void run() { synchronized (Lock1) { System.out.println("Thread 1: Holding lock 1...");

        </span><span class="kwd">try</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">Thread</span><span class="pun">.</span><span class="pln">sleep</span><span class="pun">(</span><span class="lit">10</span><span class="pun">);</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
        </span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(</span><span class="typ">InterruptedException</span><span class="pln"> e</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
        </span><span class="typ">System</span><span class="pun">.</span><span class="kwd">out</span><span class="pun">.</span><span class="pln">println</span><span class="pun">(</span><span class="str">"Thread 1: Waiting for lock 2..."</span><span class="pun">);</span><span class="pln">
        
        </span><span class="kwd">synchronized</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Lock2</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
           </span><span class="typ">System</span><span class="pun">.</span><span class="kwd">out</span><span class="pun">.</span><span class="pln">println</span><span class="pun">(</span><span class="str">"Thread 1: Holding lock 1 &amp; 2..."</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
     </span><span class="pun">}</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">

} private static class ThreadDemo2 extends Thread { public void run() { synchronized (Lock2) { System.out.println("Thread 2: Holding lock 2...");

        </span><span class="kwd">try</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">Thread</span><span class="pun">.</span><span class="pln">sleep</span><span class="pun">(</span><span class="lit">10</span><span class="pun">);</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
        </span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(</span><span class="typ">InterruptedException</span><span class="pln"> e</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
        </span><span class="typ">System</span><span class="pun">.</span><span class="kwd">out</span><span class="pun">.</span><span class="pln">println</span><span class="pun">(</span><span class="str">"Thread 2: Waiting for lock 1..."</span><span class="pun">);</span><span class="pln">
        
        </span><span class="kwd">synchronized</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Lock1</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
           </span><span class="typ">System</span><span class="pun">.</span><span class="kwd">out</span><span class="pun">.</span><span class="pln">println</span><span class="pun">(</span><span class="str">"Thread 2: Holding lock 1 &amp; 2..."</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
     </span><span class="pun">}</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">

} }

编译并执行上述程序时,发现死锁情况,以下是该程序产生的输出:

Thread 1: Holding lock 1...
Thread 2: Holding lock 2...
Thread 1: Waiting for lock 2...
Thread 2: Waiting for lock 1...

上面的程序将永远挂起,因为两个线程都无法继续进行并等待彼此释放锁,因此可以通过按CTRL + C退出程序。

死锁解决示例

让无涯教程更改同一程序的锁定和运行顺序,以查看两个线程是否仍然彼此等待-

public class TestThread {
   public static Object Lock1 = new Object();
   public static Object Lock2 = new Object();

public static void main(String args[]) { ThreadDemo1 T1 = new ThreadDemo1(); ThreadDemo2 T2 = new ThreadDemo2(); T1.start(); T2.start(); }

private static class ThreadDemo1 extends Thread { public void run() { synchronized (Lock1) { System.out.println("Thread 1: Holding lock 1...");

        </span><span class="kwd">try</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
           </span><span class="typ">Thread</span><span class="pun">.</span><span class="pln">sleep</span><span class="pun">(</span><span class="lit">10</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(</span><span class="typ">InterruptedException</span><span class="pln"> e</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
        </span><span class="typ">System</span><span class="pun">.</span><span class="kwd">out</span><span class="pun">.</span><span class="pln">println</span><span class="pun">(</span><span class="str">"Thread 1: Waiting for lock 2..."</span><span class="pun">);</span><span class="pln">
        
        </span><span class="kwd">synchronized</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Lock2</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
           </span><span class="typ">System</span><span class="pun">.</span><span class="kwd">out</span><span class="pun">.</span><span class="pln">println</span><span class="pun">(</span><span class="str">"Thread 1: Holding lock 1 &amp; 2..."</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
     </span><span class="pun">}</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">

} private static class ThreadDemo2 extends Thread { public void run() { synchronized (Lock1) { System.out.println("Thread 2: Holding lock 1...");

        </span><span class="kwd">try</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
           </span><span class="typ">Thread</span><span class="pun">.</span><span class="pln">sleep</span><span class="pun">(</span><span class="lit">10</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(</span><span class="typ">InterruptedException</span><span class="pln"> e</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
        </span><span class="typ">System</span><span class="pun">.</span><span class="kwd">out</span><span class="pun">.</span><span class="pln">println</span><span class="pun">(</span><span class="str">"Thread 2: Waiting for lock 2..."</span><span class="pun">);</span><span class="pln">
        
        </span><span class="kwd">synchronized</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Lock2</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
           </span><span class="typ">System</span><span class="pun">.</span><span class="kwd">out</span><span class="pun">.</span><span class="pln">println</span><span class="pun">(</span><span class="str">"Thread 2: Holding lock 1 &amp; 2..."</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
     </span><span class="pun">}</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">

} }

因此,只需更改锁的顺序即可防止程序陷入死锁情况,并完成以下输出:

Thread 1: Holding lock 1...
Thread 1: Waiting for lock 2...
Thread 1: Holding lock 1 & 2...
Thread 2: Holding lock 1...
Thread 2: Waiting for lock 2...
Thread 2: Holding lock 1 & 2...

参考链接

www.learnfk.com/java/java-t…