同步块中的线程睡眠方法行为

时间:2017-01-05 16:13:33

标签: synchronized thread-sleep

public class DeadlockDemo2 {

    public static Object Lock1 = new Object();
    public static Object Lock2 = new Object();

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        ThreadDemo1 demo1 = new ThreadDemo1();
        ThreadDemo2 demo2 = new ThreadDemo2();
        demo1.start();
        demo2.start();
    }

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

                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                }
                System.out.println("Thread 1: Waiting for lock 2...");

                synchronized (Lock2) {
                    System.out.println("Thread 1: Holding lock 1 & 2...");
                }
            }
        }
    }

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

                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                }
                System.out.println("Thread 2: Waiting for lock 1...");

                synchronized (Lock1) {
                    System.out.println("Thread 2: Holding lock 1 & 2...");
                }
            }
        }
    }
}

在上面的程序中,两个线程都在休眠10毫秒。所以一旦时间到期,demo1就可以锁定lock1上的lock2和demo2。但事实并非如此。他们陷入僵局。

有人可以解释原因吗?

提前致谢。

1 个答案:

答案 0 :(得分:0)

我们将忽略这里的设计问题,并假设您只是试图通过玩具示例来理解线程。

问题是你的锁定范围。我们在这里列出操作顺序:

ThreadDemo1

  1. 获取Lock1
  2. 睡眠
  3. 获取Lock2
  4. 免费Lock2
  5. 免费Lock1
  6. 同样,在ThreadDemo2

    1. 获取Lock2
    2. 睡眠
    3. 获取Lock1
    4. 免费Lock1
    5. 免费Lock2
    6. 从这里的操作顺序可以看出,在释放初始锁定之前,两个ThreadDemo类都尝试获取另一个锁。这基本上保证了死锁,因为它们将永远停留在等待对方释放其初始锁定。

      你真正想要发生的是ThreadDemo1

      1. 获取Lock1
      2. 睡眠
      3. 免费Lock1
      4. 获取Lock2
      5. 免费Lock2
      6. 这是ThreadDemo2

        1. 获取Lock2
        2. 睡眠
        3. 免费Lock2
        4. 获取Lock1
        5. 免费Lock1
        6. 要做到这一点,只需更改:

          private static class ThreadDemo1 extends Thread {
              public void run() {
                  synchronized (Lock1) {
                      System.out.println("Thread 1: Holding lock 1...");
          
                      try {
                          Thread.sleep(10);
                      } catch (InterruptedException e) {
                      }
                      System.out.println("Thread 1: Waiting for lock 2...");
          
                      synchronized (Lock2) {
                          System.out.println("Thread 1: Holding lock 1 & 2...");
                      }
                  } // <----- We're going to move this bracket
              }
          }
          

          对此:

          private static class ThreadDemo1 extends Thread {
              public void run() {
                  synchronized (Lock1) {
                      System.out.println("Thread 1: Holding lock 1...");
          
                      try {
                          Thread.sleep(10);
                      } catch (InterruptedException e) {
                      }
                  } // <----- We moved it here
                  System.out.println("Thread 1: Waiting for lock 2...");
          
                  synchronized (Lock2) {
                      System.out.println("Thread 1: Holding lock 1 & 2...");
                  }
              }
          }
          

          ThreadDemo2班级中进行相同的更改