我最近在学习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
    {     
     bankLock.unlock();
     sufficientFund.signalAll();
    } 
}程序在运行过程中会出现异常:Exception in thread "Thread-0" java.lang.IllegalMonitorStateException
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.signalAll(AbstractQueuedSynchronizer.java:1680)
at syntest.Bank.transfer(SynchBankTest.java:58)
at syntest.TransferRunnable.run(SynchBankTest.java:107)
at java.lang.Thread.run(Thread.java:595)
Exception in thread "Thread-1" java.lang.IllegalMonitorStateException
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.signalAll(AbstractQueuedSynchronizer.java:1680)
at syntest.Bank.transfer(SynchBankTest.java:58)
at syntest.TransferRunnable.run(SynchBankTest.java:107)
at java.lang.Thread.run(Thread.java:595)
......(异常继续)我不知道为什么将sufficientFund.signalAll();放到bankLock.unlock();之后会出现如此的异常。难道线程调用条件对象的signalall()方法必须在释放锁之前?
请高手赐教!