锁对象
用ReentrantLock保护代码块基本结构:
public class Bank {
private Lock bankLock = new ReentrantLock();
...
public void transfer(int from, int to, int amount) {
bankLock.lock();
try {
...
} finally {
bankLock.unlock(); //确保临界区代码抛出异常,锁必须被释放
}
}
}
每个Bank对象都有自己的ReentrantLock对象。访问不同的Bank对象,会得到不同的锁对象。
锁是可重入的,获得锁的线程可以重复获得相同的锁,调用其他使用相同锁的方法,锁用一个持有计数来跟踪对lock方法的嵌套调用。
条件对象
线程进入临界区,发现需要某条件满足后才能执行。需要使用一个条件对象来管理获得锁但无法执行的线程。
一个锁对象可以有一个或多个相关的条件对象,使用newCondition方法获得一个条件对象。
condition.await(); 线程阻塞,放弃锁,进入该条件的等待集
condition.signalAll(); 唤醒所有等待该条件的线程,解除阻塞状态,线程试图重新获得锁
class Bank
{
private final double[] accounts;
private Lock bankLock;
private Condition sufficientFunds;
public Bank() {
...
bankLock = new ReentrantLock();
sufficientFunds = bankLock.newCondition();
}
public void transfer(int from, int to, int amount) throws InterruptedException{
bankLock.lock();
try {
while (accounts[from] < amount)
sufficientFunds.await(); //账户钱不够线程阻塞
//transfer
sufficientFunds.signalAll();
} finally {
bankLock.unlock();
}
}
}