如何检查此示例中的死锁
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!
或者我在这里误解了同步。
标有synchronized
的方法使用this
作为锁锁定critical-section(方法)。要进入临界区(并锁定它),线程需要获取相应的锁。如果section已经加锁,则线程阻塞在入口处,等待释放锁。
A 和 B 是线程:
- A 调用
jane.sayHello(john)
并锁定 jane
。
- B 调用
john.sayHello(jane)
并锁定 john
.
请注意 sayHello
标记为 synchronized
。
- A 调用
person.sayHelloBack(this)
,其中 person
是 john
。
- B 调用
person.sayHelloBack(this)
,其中 person
是 jane
。
注意 sayHelloBack
也标有 synchronized
。
B持有john
,所以A的调用john.sayHelloBack
被阻塞
A持有jane
,所以B的调用jane.sayHelloBack
被屏蔽
A正在等待B释放锁,反之亦然
死锁。
当我们将方法标记为 synchronized
时,它会锁定当前对象。因此,第一个线程在对象 jane
上锁定,而第二个线程在调用方法 sayHello()
.
后立即锁定对象 john
由于您已将 sayHelloBack()
也标记为同步,它会一直等到其他线程释放对调用对象的锁定。对于第一个线程,它调用 john.sayHelloBack()
,它尝试获取 john
上的锁 - 但它已被 thread-2
获取。对于第二个线程,它调用 jane.sayHellpBack()
,它尝试获取 jane
上的锁 - 但它已被 thread-1
.
获取
因此,两个线程都在等待锁,导致死锁。
目前我正在学习死锁,我发现了一个死锁的例子,但我不明白这个例子中的死锁是如何发生的。
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!
或者我在这里误解了同步。
标有synchronized
的方法使用this
作为锁锁定critical-section(方法)。要进入临界区(并锁定它),线程需要获取相应的锁。如果section已经加锁,则线程阻塞在入口处,等待释放锁。
A 和 B 是线程:
- A 调用
jane.sayHello(john)
并锁定jane
。 - B 调用
john.sayHello(jane)
并锁定john
.
请注意 sayHello
标记为 synchronized
。
- A 调用
person.sayHelloBack(this)
,其中person
是john
。 - B 调用
person.sayHelloBack(this)
,其中person
是jane
。
注意 sayHelloBack
也标有 synchronized
。
B持有
john
,所以A的调用john.sayHelloBack
被阻塞A持有
jane
,所以B的调用jane.sayHelloBack
被屏蔽A正在等待B释放锁,反之亦然
死锁。
当我们将方法标记为 synchronized
时,它会锁定当前对象。因此,第一个线程在对象 jane
上锁定,而第二个线程在调用方法 sayHello()
.
john
由于您已将 sayHelloBack()
也标记为同步,它会一直等到其他线程释放对调用对象的锁定。对于第一个线程,它调用 john.sayHelloBack()
,它尝试获取 john
上的锁 - 但它已被 thread-2
获取。对于第二个线程,它调用 jane.sayHellpBack()
,它尝试获取 jane
上的锁 - 但它已被 thread-1
.
因此,两个线程都在等待锁,导致死锁。