Это мой примерный код потоковой передачи.
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());
synchronized(bower) { //this is the change
bower.bowBack(bower);
}
}
public 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) throws InterruptedException {
final Friend alphonse =
new Friend("Alphonse");
final Friend gaston =
new Friend("Gaston");
new Thread(new Runnable() {
public void run() { alphonse.bow(gaston); }
}).start();
// Thread.sleep(20);
new Thread(new Runnable() {
public void run() { gaston.bow(alphonse); }
}).start();
}
}
Это зашло в тупик. Но если я сделаю небольшое изменение в нем. Вместо использования "bower" в качестве монитора для синхронизированного блока, я использую "this", он не заходит в тупик.
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());
synchronized(this) { //This is the change.
bower.bowBack(bower);
}
}
public 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) throws InterruptedException {
final Friend alphonse =
new Friend("Alphonse");
final Friend gaston =
new Friend("Gaston");
new Thread(new Runnable() {
public void run() { alphonse.bow(gaston); }
}).start();
// Thread.sleep(20);
new Thread(new Runnable() {
public void run() { gaston.bow(alphonse); }
}).start();
}
}
Пожалуйста, помогите мне найти правильную причину поведения, показанного выше фрагментом кода.
Разница в том, что
synchronized(objectidentifier) {
// Access shared variables and other shared resources
}
Здесь objectidentifier является ссылкой на объект, блокировка которого связана с монитором, который представляет собой синхронизированный оператор.
synchronized (bower) использует монитор от беседки, и это другой объект. Вы делаете замок для беседки. Поскольку оба потока блокируют объекты в другом потоке, происходит взаимоблокировка.
И синхронизированный (это) использует собственный монитор. Вы делаете блокировку для собственных объектов. Нити блокируют объекты в одних и тех же потоках, и никто не заботится.
Пожалуйста, поправьте меня, если я ошибаюсь!
То, что вы хотите достичь, состоит в том, что, кланяясь кому-то, вы не можете поклониться.
Я добавил бы synchronized
с методом bowBack
и удалю synchronize(this)
или synchronize(bower)
от bow...()