JavaRush /Java 博客 /Random-ZH /Java中什么是死锁?
Alexey Smirnov
第 29 级
Москва

Java中什么是死锁?

已在 Random-ZH 群组中发布
理解本文所需的知识水平:您已经完成了 Java 语法和 Java 核心任务,现在正在学习 Java 多线程。Java中的死锁或死锁是当线程对一对同步对象存在循环依赖时发生的错误。想象一下,一个线程进入对象监视器x,另一个线程进入对象监视器y。如果对象中的线程x尝试调用该对象上的任何同步方法y,并且该对象y同时尝试调用该对象上的任何同步方法x,则线程将陷入等待状态。什么是死锁? - 1下面是 java 文档教程中关于死锁这一概念的示例。这里哪里发生了线程阻塞?
public class Deadlock {
    static class Friend {
        private final String name;
        public Friend(String name) {
            this.name = name;
        }
        public String getName() {
            return this.name;
        }
        public synchronized void bow(Friend bower) {
            System.out.format("%s: %s" + "  has bowed to me!%n", this.name, bower.getName());
            bower.bowBack(this);
        }
        public synchronized void bowBack(Friend bower) {
            System.out.format("%s: %s"
                + " has bowed back to me!%n",
                this.name, bower.getName());
        }
    }

    public static void main(String[] args) {
        final Friend alphonse =
            new Friend("Alphonse");
        final Friend gaston =
            new Friend("Gaston");
        new Thread(new Runnable() {
            @Override
            public void run() {
               // System.out.println("Thread 1");
                alphonse.bow(gaston);
               // System.out.println("Th: gaston bowed to alphonse");
            }
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
              //  System.out.println("Thread 2");
                gaston.bow(alphonse);
              //  System.out.println("2.gaston waiting alph bowed");
            }
        }).start();
    }
}
这里有两件重要的事情需要理解:
  1. 每个并发运行的线程到底做什么?
  2. 使用什么锁?
让我们从最后开始吧。假设您创建了该类的两个对象Friendalphonsegaston。他们每个人都有自己的锁。因此,这些锁有两种:舞男和加斯顿。当进入对象的同步方法时,它的锁被锁定,当退出该方法时,它被释放(或解锁)。现在关于线程。让我们调用第一个线程Alphonse(用大写字母来区分它与对象 alphonse)。它的作用如下(我们称之为A,简称Alphonse):
A: alphonse.bow(gaston) — получает лок alphonse;
A: gaston.bowBack(alphonse) — получает лок gaston;
A: возвращается из обоих методов, тем самым освобождая лок.
这是线程此时正在执行的操作Gaston
G: gaston.bow(alphonse) — получает лок gaston;
G: alphonse.bowBack(gaston) — получает лок alphonse;
G: возвращается из обоих методов, тем самым освобождая лок.
现在让我们将这些数据放在一起并得出答案。线程可以以不同的顺序交织在一起(即它们的事件将发生)。例如,如果顺序如下:
A: alphonse.bow(gaston) — получает лок alphonse
G: gaston.bow(alphonse) — получает лок gaston
G: пытается вызвать alphonse.bowBack(gaston), но блокируется, ожидая лока alphonse
A: пытается вызвать gaston.bowBack(alphonse), но блокируется, ожидая лока gaston
什么是死锁? - 2
在这种情况下,两个线程都被阻塞,并且每个线程都在等待对方释放锁。但他们都不会这样做,因为要做到这一点,他们需要完成他们的方法,并且它被另一个线程阻塞。所以他们被困在事情发生的地方deadlock。然而,另一种编织也是可能的,其中一个线程将有时间在第二个线程开始之前完成:
A: alphonse.bow(gaston) — получает лок alphonse
A: gaston.bowBack(alphonse) — получает лок gaston
A: возвращается из обоих методов, открывая оба лока
G: gaston.bow(alphonse) — получает лок gaston
G: alphonse.bowBack(gaston) — получает лок alphonse
G: возвращается из обоих методов, открывая оба лока
在这种情况下,线程之间不存在相互阻塞。例如,添加了一些方法,允许另一个线程有时间执行。当结果取决于同时发生的事件的顺序(计划顺序或执行速度)时,这样的过程在俄语中称为竞争条件 - “竞争条件”。并非所有竞争条件都可能导致死锁,但是,根据我的经验,只有竞争条件才会导致死锁。 回答者: 戴夫·利勒森
评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION