Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/380.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 僵局在哪里?_Java_Multithreading - Fatal编程技术网

Java 僵局在哪里?

Java 僵局在哪里?,java,multithreading,Java,Multithreading,这是java文档中关于死锁的教程。我不知道线程被阻塞的地方。因为它是同步的,我想只有一根线会进入弓。但两人都进了船头。[等待[但何时?]] 那么问题在哪里呢 当我添加注释[将语句打印到跟踪]时。没有僵局。怎么做 public class Deadlock { static class Friend { private final String name; public Friend(String name) { this.name

这是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();
    }
}
输出为:

Alphonse: Gaston  has bowed to me!
Gaston: Alphonse  has bowed to me!

没有人会退缩

这里有两个独立的对象-synchronized关键字不会阻止在对象1中与在对象2中同时调用bow。它只会阻止两个线程进入同一对象的同步方法


然后输入两个方法,每个对象上都有锁。然后,两者都不能输入另一个对象的方法,因为同步关键字在对象级别上工作。

您在那里有两个单独的对象-同步关键字不会阻止在对象1中与在对象2中同时调用bow。它只会阻止两个线程进入同一对象的同步方法


然后输入两个方法,每个对象上都有锁。然后两者都不能进入另一个对象的方法,因为同步关键字在对象级别工作。

首先,调用
System.out.println()
会带来大量资源,因此会在处理过程中造成有效延迟,从而人为地导致/避免并发问题。不要过多地了解添加打印的效果

现在,当线程a锁X然后锁Y,同时线程B锁Y然后锁X时,就会发生死锁。如果两个线程都获得了第一个锁,那么两个线程都不能继续=死锁


在您的例子中,方法
bow()
锁定它所调用的实例,但是从该锁中调用bowe的bow方法:同步是锁定实例,因此两个单独的实例都可以获得它们的第一个锁。第二个锁在另一个实例上,因此两个线程都在等待另一个线程持有的锁=死锁。

首先,调用
System.out.println()
会带来大量资源,因此会在处理过程中产生有效延迟,从而人为地导致/避免并发问题。不要过多地了解添加打印的效果

现在,当线程a锁X然后锁Y,同时线程B锁Y然后锁X时,就会发生死锁。如果两个线程都获得了第一个锁,那么两个线程都不能继续=死锁


在您的例子中,方法
bow()
锁定它所调用的实例,但是从该锁中调用bowe的bow方法:同步是锁定实例,因此两个单独的实例都可以获得它们的第一个锁。第二个锁位于另一个实例上,因此两个线程都在等待另一个线程持有的锁=死锁。

对此进行了精确解释。由于第一个对象试图调用第二个对象上的某个对象,第二个对象在到达同步块后一直在等待,所以对bowBack()的第一个调用永远不会结束,两个调用都会被卡住。读这篇文章。第一次我没有注意到你在从另一个对象调用
bower.getName()
bower.getName()
调用导致死锁

解释得很清楚。由于第一个对象试图调用第二个对象上的某个对象,第二个对象在到达同步块后一直在等待,所以对bowBack()的第一个调用永远不会结束,两个调用都会被卡住。读这篇文章。第一次我没有注意到你在从另一个对象调用
bower.getName()
bower.getName()
调用导致死锁

考虑到某个时间点,“Alphonse”和“Gaston”都开始鞠躬,这意味着它们已经分别拥有了自己的锁。然后他们都希望另一方同时向对方鞠躬,这意味着他们都试图获得对方的锁。由于两个锁都被占用,因此
bowBack()
调用将被阻止。由于
bowBack()
bow()
块中,因此
bow()
函数不能立即返回。因此,当他们已经获得了一些资源,但仍然试图获得一些已经占用的其他资源时,他们处于僵局状态。

考虑到某个时间点,“阿尔方斯”和“加斯顿”都开始鞠躬,这意味着他们已经分别拥有了自己的锁。然后他们都希望另一方同时向对方鞠躬,这意味着他们都试图获得对方的锁。由于两个锁都被占用,因此
bowBack()
调用将被阻止。由于
bowBack()
bow()
块中,因此
bow()
函数不能立即返回。因此,当他们已经获得一些资源,但仍然试图获得一些已经占用的其他资源时,他们就处于死锁状态。

这里需要了解两件重要的事情:1)每个并发运行的线程在做什么?2)涉及哪些锁

首先,您创建了Friend类的两个实例:alphonse和gaston。每个对象都有自己的锁。所以有两种锁:阿尔方斯锁和加斯顿锁。当您输入对象的同步方法时,它会锁定该对象的锁。当同步方法返回时,锁被释放(解锁)

现在是线程。您的第一个线程,我们称之为Alphone的线程(注意大写字母A以区分线程和对象,alphonse)执行以下操作:(“A:”表示这是alphonse的线程。)

同时,Gaston的线程执行以下操作:(“G:”表示这是Gaston的线程。)

现在我们可以把这两个信息放在一起,得出我们的答案。线程可以以不同的顺序交错(即,它们的事件发生)。例如,如果事件按以下顺序发生,则会发生死锁:

A: alphonse.bow(gaston) - acquires alphonse's lock
G: gaston.bow(alphonse) - acquires gaston's lock
G: attempts to call alphonse.bowBack(gaston), but blocks waiting on alphonse's lock
A: attempts to call gaston.bowBack(alphonse), but blocks waiting on gaston's lock to
在这种情况下,每个线程都被阻塞,等待获取
G: gaston.bow(alphonse) - acquires gaston's lock
G: alphonse.bowBack(gaston) - acquires alphonse's lock
G: both methods return, thus releasing both locks
A: alphonse.bow(gaston) - acquires alphonse's lock
G: gaston.bow(alphonse) - acquires gaston's lock
G: attempts to call alphonse.bowBack(gaston), but blocks waiting on alphonse's lock
A: attempts to call gaston.bowBack(alphonse), but blocks waiting on gaston's lock to
A: alphonse.bow(gaston) - acquires alphonse's lock
A: gaston.bowBack(alphonse) - acquires gaston's lock
A: both methods return, thus releasing both locks
G: gaston.bow(alphonse) - acquires gaston's lock
G: alphonse.bowBack(gaston) - acquires alphonse's lock
G: both methods return, thus releasing both locks