Lock-ordering deadlocks
不同线程,获得获得相同多个锁的顺序不同导致死锁:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
public class LeftRightDeadlock {
private final Object left = new Object();
private final Object right = new Object();
public void leftRight() {
synchronized (left) {
synchronized (right) {
doSomething();
}
}
}
public void rightLeft() {
synchronized (right) {
synchronized (left) {
doSomething();
}
}
}
}
|
Dynamic lock order deadlocks
根据参数来决定locking顺序同样有死锁风险:
1
2
3
4
5
6
7
|
public void transferMoney(Account from, Account to, double amount) {
synchronized (from) {
synchronized (to) {
doSomething();
}
}
}
|
解决办法:根据参数来推导出固定的locking顺序:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
priate static final Object tieLock = new Object();
public void transferMoney(Account from, Account to, double amount) {
long fromHash = System.identityHashCode(from);
long toHash = System.identityHashCode(to);
if (fromHash < toHash) {
synchronized (from) {
synchronized (to) {
doSomething();
}
}
} else if (toHash < fromHash) {
synchronized (to) {
synchronized (from) {
doSomething();
}
}
} else {
synchronized (tieLock) {
// 当出现hash相同的情况时,全部都穿行到tieLock下执行
synchronized (from) {
synchronized (to) {
doSomething();
}
}
}
}
}
|
Deadlocks between cooperating object
因为多个对象的协作导致的比较隐蔽的死锁:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
class Taxi {
private final Dispatcher dispatcher;
public synchronized Point getLocation() {
// ...
}
public synchronized void setLocation(Point location) {
this.location = location;
// alien method
dispatcher.notifyAvailable(this);
}
}
class Dispatcher {
private final Set<Taxi> taxis;
public synchronized void notifyAvailable(Taxi taxi) {
// ...
}
public synchronized Image getImage() {
Image image = new Image();
for (Taxi taxi : taxis) {
// alien method
image.drawMarker(taxi.getLocation());
}
return image;
}
}
|
Open calls
用Open calls改造,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
class Taxi {
private final Dispatcher dispatcher;
public synchronized Point getLocation() {
// ...
}
public void setLocation(Point location) {
synchronized (this) {
this.location = location;
}
// alien method
dispatcher.notifyAvailable(this);
}
}
class Dispatcher {
private final Set<Taxi> taxis;
public synchronized void notifyAvailable(Taxi taxi) {
// ...
}
public Image getImage() {
Set<Taxi> copy;
// 限制了在调用alien方法时,本身不持有锁
synchronized (this) {
copy = new HashSet<>(taxis);
}
Image image = new Image();
for (Taxi taxi : copy) {
// alien method
image.drawMarker(taxi.getLocation());
}
return image;
}
}
|
评论