【问题标题】:Deadlocks using wait and notify使用等待和通知的死锁
【发布时间】:2014-11-13 02:34:02
【问题描述】:

我试图了解死锁是如何产生的。我了解到,通过在两个同步方法上使用两个线程,可以创建死锁。 看了很多网上的例子。

可以通过等待和通知创建死锁吗? 每次线程处于等待状态时,都会收到通知。那么这怎么会陷入僵局呢?

举例说明会有帮助。

【问题讨论】:

标签: java deadlock


【解决方案1】:
Deadlock is caused when two threads try to obtain the same, multiple locks in different order:

    // T1
    synchronized (A) {
      synchronized (B) {
        // ...
      }
    }

    // T2
    synchronized (B) {
      synchronized (A) {
        // ...
      }

}

防止死锁的唯一方法是确保所有线程以相同的顺序获得锁——要么他们都做A然后B,或者他们都做B然后A。

如果您没有多个锁,那么您就没有死锁。但是,您可能会遇到线程不足或其他可能类似于死锁的情况。

【讨论】:

    【解决方案2】:

    假设线程 1 在方法 A 上进入一个同步块,然后等待。然后线程 2 尝试进入方法 A 的同步块。线程 1 正在等待通知,线程 2 正在等待同步块。现在一切都在等待。其他一些线程将不得不通知线程 1 正在等待的对象。这只是可能造成死锁的一种情况。有各种各样的方法可以做到这一点。

    【讨论】:

    • 引用Object#wait javadoc:“线程释放此监视器的所有权并等待[...]”
    【解决方案3】:

    除非某些代码明确通知它,否则不会通知处于等待状态的线程。因此,您正在寻找的示例绝对是微不足道的:

    public static void main(String[] args) {
       synchronized(String.class) {
           String.class.wait();
       }
    }
    

    这将永远挂起。但从技术上讲,它不是死锁,它需要两个或多个线程参与一个封闭循环,每个线程等待下一个线程解除阻塞。

    【讨论】:

    • 如果 JVM 在无法取得进展的情况下在其中一个被阻塞的线程中引发一些异常,那就太好了。
    • @Ingo 为什么 JVM 的工作应该是解决糟糕的编程?
    • @b1nary.atr0phy 你会调用 NullPointerException 来治愈糟糕的编程吗?不,这只是诊断问题,这是 JVM 的工作。
    • @Ingo 苹果和橙子。 JVM 是否应该检测你是否也想要 --x 而不是 x++?
    • @b1nary.atr0phy 另一方面,JVM 为什么要检测空指针或内存不足?答:因为 1)它可以,并且 2)它让我们的生活更轻松。
    【解决方案4】:

    接近等待/通知死锁的事情:

    public class Example
    {
        volatile boolean isNotified = false;
    
        public synchronized void method1() {
            try
            {
                isNotified = false;
                while (!isNotified)
                    wait();
                notifyAll();
                System.out.println("Method 1");
            } catch (InterruptedException e) {/*NOP*/}
        }
    
        public synchronized void method2() {
            try {
                isNotified = true;
                while (isNotified)
                    wait();
                notifyAll();
    
                System.out.println("Method 2");
            } catch (InterruptedException e) {/*NOP*/}
    
        }
    
        public static void main(String[] args)
        {
            Example example = new Example();
    
            Thread thread1 = new Thread()
            {
    
                public void run()
                {
                    example.method1();
                }
            };
    
            Thread thread2 = new Thread()
            {
    
                public void run()
                {
                    example.method2();
                }
            };
    
            thread1.start();
            thread2.start();
        }
    }
    

    【讨论】:

    • 这会如何造成死锁?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-12
    • 2015-09-20
    相关资源
    最近更新 更多