java多线程与线程池(三):几种实现加锁的方法(2)——synchronized关键字
昨天写了Lock+Condition的加锁机制,今天根据书上内容来总结一下有关锁和条件的关键之处:
锁用来保护代码片段,任何时刻只能有一个线程执行被保护的代码。
锁可以管理试图进入被保护代码段的线程。
锁可以拥有一个或者多个相关的条件对象(使用Lock.newCondition创建)
每个条件对象管理那些已经进入被保护的代码段但不满足条件还不能运行的线程。
今天,我们再来说说java中每个对象都有的一个内部锁,如果使用一个方法用synchonized关键字声明,那么对象的锁就会保护整个方法。要调用该方法,线程必须获得内部的对象锁。(在方法使用synchronized关键字声明时,不需要在获取对象内部锁了,且也无需使用try-finally)
内部对象锁只有一个相关条件,wait方法添加一个线程到等待集中,notifyAll解除等待线程的阻塞状态,相较于条件对象来说,wait()=Condition.await(); notifyAll()=Condition.signalAll();
接下来是使用synchronized 关键字的代码:
public class Bank { private final double[] accouts; private Lock banklock; private Condition sufficientFunds; public Bank(int n,double initialBalance) { accouts = new double[n]; Arrays.fill(accouts, initialBalance); banklock = new ReentrantLock(); sufficientFunds = banklock.newCondition(); } public synchronized void transfer(int from, int to, double amount) throws InterruptedException{ while (accouts[from] < amount) wait(); System.out.println(Thread.currentThread()); accouts[from] -= amount; System.out.printf("%10.2f from %d to %d, remain %10.2f", amount, from, to,accouts[from]); accouts[to] += amount; System.out.printf(" Total Balance: %10.2f%n", getTotalBalance()); notifyAll(); } public synchronized double getTotalBalance() { double sum = 0; for (double a : accouts) sum += a; return sum; } public int size(){ return accouts.length; } }