I got this deadlock sample codes from oracle.
class Thread_Test {
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() {
public void run() { alphonse.bow(gaston); }
}).start();
new Thread(new Runnable() {
public void run() { gaston.bow(alphonse); }
}).start();
}
}
If I change function bow like below, I can resolve the deadlock issue.
public void bow(Friend bower) {
synchronized(this) {
System.out.format("%s: %s" + " has bowed to me!%n", this.name, bower.getName());
}
bower.bowBack(this);
}
Can I use other approaches to resolve this deadlock issue.
Especially, I wonder that Thread.sleep() can be a solution for deadlock and how I can use it.
Could you let me know about the possibility of Thread.sleep() and other approaches?
Thanks alot
You need to lock on 2 objects at once (Let's call them A and B). here is a nice explaination of what might happen. To fix that, you could try to always lock in same order:
static class Friend {
private static int idCounter;
private final int id;
private final String name;
public Friend(String name) {
this.name = name;
id = idCounter++;
}
public String getName() {
return this.name;
}
public void bow(Friend bower) {
Friend first, second;
if(bower.id > id) {
first = this;
second = bower;
} else {
first = bower;
second = this;
}
synchronized(first) {
synchronized(second) {
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());
}
}
Here the Friend with lower id gets locked first, so the deadlock now should't happen.
The deadlock is occurring because the following method calls occur:
The reason your solution works is that the bowBack(this) call is outside of the synchronized block.
Smart use of Locks can both demonstrate more clearly why and exactly where deadlock is occurring, and can prevent it. Java's Semaphore class is a nice one to look into.
To actually fix it (prevent deadlock but keep it thread safe), you have to expand on the problem - what should happen when Gaston is waiting for Alphonse to finish bow() to execute his own bow(), but Alphonse needs Gason to execute a bowBack() to finish? One sensible solution is for Gaston to give up on executing bow() when the call to bowBack() comes and just execute bowBack(), but it all depends on what problem you're trying to solve.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With