繁体   English   中英

死锁情况的Java代码?

[英]java code for deadlock situation?

这是代码

public class TestDeadlockExample1 {
     public static void main(String[] args) {  
            final String resource1 = "xyz";  
            final String resource2 = "pqr";  
            // t1 tries to lock resource1 then resource2  
            Thread t1 = new Thread() {  
              public void run() {  
                  synchronized (resource1) {  
                   System.out.println("Thread 1: locked resource 1");  

                   try { Thread.sleep(10000);} catch (Exception e) {}  

                   synchronized (resource2) {  
                    System.out.println("Thread 1: locked resource 2");  
                   }  
                 }  
              }  
            };  

            // t2 tries to lock resource2 then resource1  
            Thread t2 = new Thread() {  
              public void run() {  
                synchronized (resource2) {  
                  System.out.println("Thread 2: locked resource 2");  

                  try { Thread.sleep(10000);} catch (Exception e) {}  

                  synchronized (resource1) {  
                    System.out.println("Thread 2: locked resource 1");  
                  }  
                }  
              }  
            };  


            t1.start();  
            t2.start();  
            System.out.println("completed");
          }  
}


here 

 t1.start();  
 t2.start();  
 System.out.println("completed");

这里

在此t1.start()和t2.start()中是按顺序编写的,所以我怀疑这两个线程是否以相同的方式启动,或者t1开始,执行然后到达t2并执行(如果正确),这怎么会变成死锁情况..我想知道这些线程的执行情况

启动Java程序时,JRE产生主线程,并且该主线程执行您的main方法。

当您调用t1.start() ,新线程会生成并执行第一个匿​​名类的run方法。 从这时起,程序中将同时执行2个线程:“主线程”和“线程1”。

当您调用t2.start() ,另一个线程会生成并执行第二个匿名类的run方法。 从这时起,程序中将同时执行3个线程:“主线程”,“线程1”,“线程2”。

未定义线程的执行顺序。 可能是任何东西。 通常,它们是同时执行的。

您的“线程1”和“线程2”分别获得对resource1resource2锁定,并睡眠10秒钟。 在这种情况下,您的“主”线程完成了执行。 但是您的程序中还有2个线程,因此当main方法完成时,程序尚未完成。

在休眠“线程1”和“线程2”之后,尝试获取resource 2resource 1锁,但是这些锁已经被获取,因此它们将等待直到锁持有者将其释放。 锁持有者将永远不会释放它,因为它等待其他资源,因此该程序永远不会停止。 那是典型的僵局情况。

我了解到,要防止死锁,您需要使synchronized块保持一致。

          public void run() {  
              synchronized (resource1) {  
              synchronized (resource2) {  
               System.out.println("Thread 1: locked resource 1");  
               System.out.println("Thread 1: locked resource 2");  
               try { Thread.sleep(10000);} catch (Exception e) {}  
               }  
             }  
          }  

        Thread t2 = new Thread() {  
          public void run() {  
            synchronized (resource1) {  
            synchronized (resource2) {  
              System.out.println("Thread 2: locked resource 2");  
              System.out.println("Thread 2: locked resource 1");  
              try { Thread.sleep(10000);} catch (Exception e) {}  
              }  
            }  
          }  
        };  

在此t1.start()和t2.start()是按顺序编写的,因此我的疑问是两个线程是否以相同的方式启动,或者t1开始,执行然后进入t2并执行

调用start()不能确保Thread 立即启动。 通过start0()进行本机调用,然后调用OS派生线程。 因此,基本上,线程2可以在线程1之前启动。 您无法控制哪个线程首先启动。

这如何成为僵局

这里存在死锁的可能性,因为t1可能同时锁定resource1t2可能同时锁定resource2 现在,两个线程都希望另一个线程拥有该资源。 因此,您将陷入僵局。

因此,作为标准做法, t1t2都应以相同的顺序获得锁定。

sleep()保证t1和t2都先获得第一把锁,然后再进行第二把锁。 无论哪个线程先运行。

“所以我怀疑这两个线程是否在同一时间启动,或者t1启动,执行然后到t2并执行”

仅仅因为线程t1和t2是顺序生成的,并不意味着它们是顺序执行的。 线程用于并行执行工作单元。

由于代码中的sleep方法调用,它将死锁,因为

  1. t1获取R1或t2获取t2。 顺序不确定

  2. 两个线程在获取各自的资源后都会休眠10秒钟,因此在本示例中可以肯定地说,两个线程在另一个的睡眠期间的某个时间点已获取了资源。

  3. 当t1或t2唤醒并尝试获取第二资源时,该资源已被同级线程占用,它将阻塞。 两个线程都将阻止尝试获取另一个线程所拥有的资源。

仅因为线程并行执行而不是顺序执行,才会发生这种情况。

请参阅http://docs.oracle.com/javase/tutorial/essential/concurrency/deadlock.html

未定义线程执行的顺序。

您的程序陷入死锁的风险很高。 但是您可以稍微更改第二个线程中的锁定顺序,以避免死锁。 我已经修改并在下面给出。 同样,这取决于要编写的逻辑。

Thread t2 = new Thread() {  
  public void run() {  
    synchronized (resource1) {  
      System.out.println("Thread 2: locked resource 2");  

      try { Thread.sleep(10000);} catch (Exception e) {}  
      System.out.println("Thread 2: Waiting for resource 1...");
      synchronized (resource2) {  
        System.out.println("Thread 2: locked resource 1 and 2");  
      }  
    }  
  }  
};

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM