在前面一节中 , 介绍了如何使用 Lock 和 Condition 对象。 然而,大多数情况下,并不需要那样的控制,并且可以使用一种嵌人到Java 语言内部的机制 。从 1.0 版开始,Java中的每一个对象都有一个内部锁.如果一个方法用 synchronized
关键字声明 ,那么对象的锁将保护整个方法.也就是说,要调用该方法,线程必须获得内部的对象锁 。
如下:
public synchronized void method () {
method body
}
等价于
public void method () {
this.intrinsidock.1ock();
try{
method body
}
finally{ this.intrinsidock.unlock(); }
}
因此,针对之前银行的问题,我们可以简单的将Bank
类的transfer
方法为synchronized
,而不是使用显性的锁。
当内部对象锁相关条件不满足时,调用wait()
方法添加该线程到等待集中,notifyAll()/notify
方法用于解除当前等待线程的阻塞状态。
所以wait()
和notifyAll()/notify
方法等价于intrinsidock.await()/intrinsidock.signalAll()
.
于是,Bank
类可以改为:
public class Bank
{
public Bank(int n, double initialBalance)
{
accounts = new double[n];
for (int i = 0; i < accounts.length; i++)
accounts[i] = initialBalance;
}
//使用synchronized 修饰transfer方法,给该方法加锁
public synchronized void transfer(int from, int to, double amount) throws InterruptedException
{
while (accounts[from] < amount)
wait();
System.out.print(Thread.currentThread());
accounts[from] -= amount;
System.out.printf(" %10.2f from %d to %d", amount, from, to);
accounts[to] += amount;
System.out.printf(" Total Balance: %10.2f%n", getTotalBalance());
notifyAll();
}
//同理,此处的获得总金额方法也需要加锁
public synchronized double getTotalBalance()
{
double sum = 0;
for (double a : accounts)
sum += a;
return sum;
}
public int size()
{
return accounts.length;
}
private final double[] accounts;
}