我最近在学习Core Java 2 第二卷,看到1.5.4节(条件对象)的示例代码时,遇到了一个问题:
在 JDK1.5 中, java.util.concurrent.locks.Lock用于保护代码片断,保证该代码片断在莫一时刻只被一个线程使用;java.util.concurrent.locks.Condition用于管理已进入被保护的代码段但还不能运行的线程。
在例1-4中,有一个类Bank,它有一个transfer方法,该方法受到了Lock的保护以及Condition的管理。transfer方法的作用是从一个账户取出一定数额的钱,放入另一个账户中。
class Bank
{
public Bank(int n, double initialBalance)
{
accounts = new double[n];
for (int i = 0; i < n; i++)
{
accounts[i] = initialBalance;
}
}
public void transfer(int from, int to, double amount) throws InterruptedException
{
bankLock.lock();
try
{
while (accounts[from] < amount)
{
sufficientFund.await();
}
System.out.println(Thread.currentThread());
accounts[from] -= amount;
System.out.println( "from " + from + " to " + to + " amount= " + amount);
accounts[to] += amount;
System.out.println( "Total Balance : " + this.getTotalBalance());
sufficientFund.signalAll();
}
finally
{
bankLock.unlock();
}
}
private double getTotalBalance()
{
bankLock.lock();
try
{
double sum = 0;
for (int i = 0; i < accounts.length; i++)
{
sum += accounts[i];
}
return sum;
}
finally
{
bankLock.unlock();
}
}
public int size()
{
return accounts.length;
}
private final double[] accounts;
private Lock bankLock = new ReentrantLock();
private Condition sufficientFund = bankLock.newCondition();
}
我一直很好奇为什么在transfer方法中,sufficientFund.signalAll();是不是只能放在如上所示的位置。后来发现,sufficientFund.signalAll();在放到bankLock.unlock();之后时,会出现异常。当我将transfer方法修改为如下代码时:
public void transfer(int from, int to, double amount) throws InterruptedException
{
bankLock.lock();
try
{
while (accounts[from] < amount)
{
sufficientFund.await();
}
System.out.println(Thread.currentThread());
accounts[from] -= amount;
System.out.println( "from " + from + " to " + to + " amount= " + amount);
accounts[to] += amount;
System.out.println( "Total Balance : " + this.getTotalBalance());
}
finally