如何检查此示例中的死锁

huangapple go评论62阅读模式
英文:

How to check deadlock in this example

问题

目前我正在学习死锁,并且我找到了一个死锁的例子,但我不明白在这个例子中是如何发生死锁的。

public class Main {

    public static void main(String[] args) {
        final PolitePerson jane = new PolitePerson("Jane");
        final PolitePerson john = new PolitePerson("John");

        new Thread(new Runnable() {
            @Override
            public void run() {
                 jane.sayHello(john);
            }
        }).start();

       new Thread(new Runnable() {
            @Override
            public void run() {
                john.sayHello(jane);
            }
        }).start();
    }

    static class PolitePerson {
        private final String name;

        public PolitePerson(String name) {
            this.name = name;
        }

        public String getName() {
            return name;
        }

        public synchronized void sayHello(PolitePerson person){
            System.out.format("%s: %s" + " has said hello to me!%n", this.name, person.getName());

            person.sayHelloBack(this);
        }

        public synchronized void sayHelloBack(PolitePerson person) {
            System.out.format("%s: %s" + " has said hello back to me!%n", this.name, person.getName());
        }
    }
}

我花了一个多小时的时间来理解这里发生的情况,但还是没有弄明白。这里是我得到的输出:

Jane: John has said hello to me!
John: Jane has said hello to me!

或者我可能对这里的同步机制有误解。

英文:

currently I am learning deadlock and I found a example of deadlock but I don't get how deadlock is occurring in this example.

public class Main {
public static void main(String[] args) {
final PolitePerson jane = new PolitePerson("Jane");
final PolitePerson john = new PolitePerson("John");
new Thread(new Runnable() {
@Override
public void run() {
jane.sayHello(john);
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
john.sayHello(jane);
}
}).start();
}
static class PolitePerson {
private final String name;
public PolitePerson(String name) {
this.name = name;
}
public String getName() {
return name;
}
public synchronized void sayHello(PolitePerson person){
System.out.format("%s: %s" + " has said hello to me!%n", this.name, person.getName());
person.sayHelloBack(this);
}
public synchronized void sayHelloBack(PolitePerson person) {
System.out.format("%s: %s" + " has said hello back to me!%n", this.name, person.getName());
}
}
}

I spend more then one hour understanding how things are happening here but didn't got it.
here is the output which I am getting

Jane: John has said hello to me!
John: Jane has said hello to me!

or maybe I misunderstood synchronisation here.

答案1

得分: 0

一个使用 synchronized 标记的方法会使用 this 作为锁来锁定临界区(即该方法)。要进入临界区(并锁定它),线程需要获取相应的锁。如果该区域已经被锁定,线程会被阻塞在入口处,并等待锁被释放。

A 和 B 是线程:

  • A 调用 jane.sayHello(john) 并锁定 jane
  • B 调用 john.sayHello(jane) 并锁定 john

注意 sayHello 被标记为 synchronized

  • A 调用 person.sayHelloBack(this),其中 personjohn
  • B 调用 person.sayHelloBack(this),其中 personjane

注意 sayHelloBack 也被标记为 synchronized

  • B 持有 john,因此 A 的调用 john.sayHelloBack 被阻塞。

  • A 持有 jane,因此 B 的调用 jane.sayHelloBack 被阻塞。

  • A 正在等待 B 释放锁,反之亦然。

  • 死锁。

英文:

A method marked with synchronized locks the critical-section (the method) using this as the lock. To enter a critical section (and lock it), a thread needs to acquire the corresponding lock. If the section is already locked, the thread is blocked at the entrance and waits for the lock to be released.

A and B are threads:

  • A calls jane.sayHello(john) and locks jane.
  • B calls john.sayHello(jane) and locks john.

Notice that sayHello is marked with synchronized.

  • A calls person.sayHelloBack(this), where person is john.
  • B calls person.sayHelloBack(this), where person is jane.

Notice that sayHelloBack is also marked with synchronized.

  • B holds john, so A's call john.sayHelloBack is blocked.

  • A holds jane, so B's call jane.sayHelloBack is blocked.

  • A is waiting for B to release the lock and vice versa.

  • Deadlock.

答案2

得分: 0

当我们将一个方法标记为synchronized时,它会在当前对象上获取一个锁。因此,第一个线程在对象jane上获取锁,而第二个线程在调用方法sayHello()时会在对象john上获取锁。

由于您还将sayHelloBack()标记为synchronized,它将等待直到另一个线程释放调用对象上的锁。对于第一个线程,它调用john.sayHelloBack(),试图在john上获取锁 - 但该锁已经被thread-2获取。对于第二个线程,它调用jane.sayHellpBack(),试图在jane上获取锁 - 但该锁已经被thread-1获取。

因此,两个线程都在那一点上等待锁,导致了死锁。

英文:

When we mark a method as synchronized, it takes a lock on the current object. So, the first thread takes a lock on the object jane whereas the second thread takes lock on the object john, as soon as it calls the method sayHello().

As you have marked the sayHelloBack() also as synchronized, it would wait until the other thread releases lock on the invoking object. For the first thread, it calls john.sayHelloBack(), it tries to acquire lock on john - but it has already been acquired by thread-2. For the second thread, it calls jane.sayHellpBack(), it tries to acquire lock on jane - but it is already acquired by thread-1.

So, both the threads keep waiting for the lock at that point causing the deadlock.

huangapple
  • 本文由 发表于 2020年8月22日 21:23:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/63536659.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定