是否可以使用同步方法编写保证经典的死锁?

时间:2018-06-23 00:24:10

标签: java multithreading deadlock

在一次采访中,我被要求写保证死锁的Java代码。我编写了一个标准代码,该代码出现在每本Java书籍中,例如创建2个线程并以不同的顺序调用同步方法,请在调用第二个线程之前睡一会儿。

当然,这些东西并不能使面试官满意,所以现在我着手找出解决方案。

我发现了一段代码:

/wordCountFile

但是我不确定这段代码是否满足他们?当然。代码永远不会结束执行,但这是一个真正的死锁吗?是不是就同步问题陷入僵局?而且,例如,我还可以编写一个无休止的循环,将public class Lock implements Runnable { static { System.out.println("Getting ready to greet the world"); try { Thread t = new Thread(new Lock()); t.start(); t.join(); } catch (InterruptedException ex) { System.out.println("won't see me"); } } public static void main(String[] args) { System.out.println("Hello World!"); } public void run() { try { Thread t = new Thread(new Lock()); t.start(); t.join(); } catch (InterruptedException ex) { System.out.println("won't see me"); } } } 放入其中并将其命名为“死锁”。

问题是:是否可以使用同步方法编写经典死锁,但100%保证? (请不要告诉我非常非常可能发生死锁的情况。我知道。)

谢谢。

3 个答案:

答案 0 :(得分:1)

创建两个资源,并让每个线程在释放另一个之前先尝试获取一个,但顺序不同。例如:

CountDownLatch a = new CountDownLatch (1);
CountDownLatch b = new CountDownLatch (1);

void one() throws InterruptedException {
  a.await();
  b.countDown();
}

void two() throws InterruptedException {
  b.await();
  a.countDown();
}

运行one的线程无法释放b,因为它正在等待a。它会一直等待,因为运行two的线程因为正在等待b而无法释放a。

一种或经典的死锁情形是您以相反的顺序获取锁。

答案 1 :(得分:0)

class Resource1 {
    synchronized static void method1() {
        try {
            Thread.sleep(1);
        } catch (InterruptedException e) {
        }
        Resource2.method1();
   }
}

class Resource2 {
    synchronized static void method1() {
        Resource1.method1();
   }
}


public class MultiThreadApp {
   public static void main(String[] args) {
       new Thread(new Runnable() {
           public void run() {
               Resource2.method1();
           }
      }).start();
      Resource1.method1();
  }
}

答案 2 :(得分:0)

public class Deadlock {
    public static void main(String[] args) {
        String res1 = "a";
        String res2 = "s";

        new Thread(
                () -> {
                    synchronized (res1) {
                        try {
                            Thread.sleep(2);
                        } catch (InterruptedException e) {
                        }
                        synchronized (res2) {
                        }
                    }
                }
        ).start();

        new Thread(
                () -> {
                    synchronized (res2) {
                        try {
                            Thread.sleep(2);
                        } catch (InterruptedException e) {
                        }
                        synchronized (res1) {
                        }
                    }
                }
        ).start();
    }
}