但是,这断代码有问题,容易产生死锁,比如两个线程分别执行: 线程1 A 转账 B 100 和 线程2 B 转账 A 300,线程1 执行到位置 1 获取到 Accoun A 对象的 锁,进行上下文切换,这时线程2 执行,到位置1 获取到 Account B 对象的锁,这样线程1持有了A的锁,线程2持有了B的锁,都相互等待对方的锁,就造成死锁了。
public class Account {
private int balance;
public synchronized void transfer(Account target, int amt) {
if (this.balance > amt) {
this.balance -= amt;
target.balance += amt;
}
}
}
public class Account {
private int balance;
private Object lock;
private Account() {}
public Account(Object lock) {
this.lock = lock;
}
public void transfer(Account target, int amt) {
synchronized (lock) {
if (this.balance > amt) {
this.balance -= amt;
target.balance += amt;
}
}
}
}
public class Account {
private int balance;
public void transfer(Account target, int amt) {
synchronized (Account.class) {
if (this.balance > amt) {
this.balance -= amt;
target.balance += amt;
}
}
}
}
// 让 Allocator 来承担资源的分配方, 保证是单例
public class Allocator {
private Set<Object> als = new HashSet<>();
// todo 缺少单例的实现 ...
private Allocator() {}
// 申请资源
public synchronized boolean apply(Object from, Object to) {
if (als.contains(from) || als.contains(to)) return false;
als.add(from);
als.add(to);
return true;
}
// 释放资源
public synchronzied void free(Object from, Object to) {
als.remove(from);
als.remove(to);
}
}
public class Account {
private Allocator allocator;
private int balance;
public void transfer(Account target, int amt) {
// 利用循环检测资源是否就绪,一次性申请所有资源
while (!allocator.apply(this, target) ;
try {
synchronized (this) { // 1
synchronized (target) { // 2
if (this.balance > amt) {
this.balance -= amt;
target.balance += amt;
}
}
}
} finally {
allocator.free(this, target);
}
}
}
public class Account {
private int id;
private int balance;
public void transfer(Account target, int amt) {
Account left = this;
Account right = target;
if (this.id > target.id) {
left = target;
right = this;
}
synchronized (left) {
synchronized (right) {
if (this.balance > amt) {
this.balance -= amt;
target.balance += amt;
}
}
}
}
}
public class Allocator {
private Set<Object> als = new HashSet<>();
// todo 缺少单例的实现 ...
private Allocator() {}
// 申请资源
public synchronized boolean apply(Object from, Object to) {
while (als.contains(from) || als.contains(to)) {
try {
wait();
} catch(Exception e) {}
}
als.add(from);
als.add(to);
}
// 释放资源
public synchronzied void free(Object from, Object to) {
als.remove(from);
als.remove(to);
notifyAll();
}
}
public class Account {
private Allocator allocator;
private int balance;
public void transfer(Account target, int amt) {
// 利用等待通知机制,一次性申请所有资源,防止死锁
allocator.apply(this, target);
try {
synchronized (this) {
synchronized (target) {
if (this.balance > amt) {
this.balance -= amt;
target.balance += amt;
}
}
}
} finally {
// 释放资源
allocator.free(this, target);
}
}
}