Several approaches to solve deadlock

This is an example from the official concurrency tutorial.
[url]http://download.oracle.com/javase/tutorial/essential/concurrency/deadlock.html[/url]

The reason for the deadlock here is that there are two sync methods

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());
}

Say, you have two objects a and b, you call them from thread1 a.bow(b) and from thread2 b.bow(a). When a holds its own lock finished printing and trying to grab b's lock(by calling b.bowBack(a)), b will be holding its own lock, finished printing and trying to grab a's lock. Here comes the deadlock.

How to solve it?
A. Use the same lock for object a and b so that they can have exclusive access to bow(). Previous deadlock situation happens because there is no exclusive access to bow(). To do this, you can pass an explicit lock to both a and b(of course add one constructor for the lock), or you can simply use Class as the lock because both a and b share the same class object.

public void bow(Friend bower) {
synchronized (this.getClass()) {
System.out.format("[%s] %s: %s has bowed to me!%n", Thread.currentThread().getName(),this.name, bower.getName());
bower.bowBack(this);
}
}

public void bowBack(Friend bower) {
synchronized (this.getClass()) {
System.out.format("[%s] %s: %s has bowed back to me!%n", Thread.currentThread().getName(),
this.name, bower.getName());
}
}


B. You can maintain a universal order for getting locks so that no matter which thread access bow(), simultaneously they can only access different parts of it.

public void bow(Friend bower) {
int hashThis = System.identityHashCode(this);
int hashBower = System.identityHashCode(bower);

if (hashThis < hashBower) {
synchronized(this) {
synchronized(bower) {
System.out.printf("[%s]: this: %d, bower: %d\n", Thread.currentThread().getName(), hashThis, hashBower);
System.out.printf("[%s] %s bow to %s\n", Thread.currentThread().getName(), this.getName(), bower.getName());
bower.bowBack(this);
}

}
} else if (hashThis > hashBower) {
synchronized(bower) {
synchronized(this) {
System.out.printf("[%s]222 %s bow to %s\n", Thread.currentThread().getName(), this.getName(), bower.getName());
bower.bowBack(this);
}
}
} else {
synchronized (getClass()) {
System.out.printf("[%s]333 %s bow to %s", Thread.currentThread().getName(), this.getName(), bower.getName());
bower.bowBack(this);
}
}
}


C. Use explicit Lock, this is the approach that is provided by this official tutorial, which should achieve the best performance at practice. One of the advantages is that the tryLock() method can grab the lock or returns false if the lock is held by other threads.
check it out. [url]http://download.oracle.com/javase/tutorial/essential/concurrency/newlocks.html[/url]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值