如果程序不使用synchronized关键字来保证同步 , 直接使用Lock对象 , 则系统中不存在隐式的同步监视器 , 也就不能使用wait(),notify(),notifyAll()方法进行通信了
当使用Lock对象来保证同步时,使用Condition可以让那些已经得到Lock对象无法继续执行的线程释放Lock对象,Condition对象也可以唤醒其他处于等待的线程。
Lock替代了同步方法或者同步代码块 , Condition替代了同步监视器的功能
Condition实例被绑定在一个Lock对象上面, 要获得Lock实例的Condition实例 , 调用Lock对象的newCondition()方法即可。
await():类似于隐士同步监视器上面的wait()方法,使当前线程等待,知道其他线程使用该Condition的signal()方法或者signalAll()方法来唤醒该线程
signal(): 唤醒在此Lock对象上等待的单个线程,如果所有线程都在Lock对象上等待,则会选择唤醒任意一个。只有当前线程放弃对该Lock对象的锁定后(使用await()方法),才可以执行被唤醒的线程
signalAll():唤醒在此Lock对象上等待的所有线程,只有当前线程放弃对该Lock对象的锁定后才可以执行被唤醒的线程。
package com.example.demo.thread; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class Account { //显示定义Lock对象 private final Lock lock = new ReentrantLock(); //获得指定Lock对象的对应Condition private final Condition condition = lock.newCondition(); private String account;//账户 private double balance;//余额 private boolean flag = false; //标识是否已有存款 , 有为true public Account() { super(); // TODO Auto-generated constructor stub } public Account(String account, double balance) { super(); this.account = account; this.balance = balance; } //账户余额不允许随便修改 , 只提供getter方法 public double getBalance() { return balance; } //取款 public void draw(double drawMoney) { lock.lock();//加锁 try { if(!flag) {//false说明没得存款 , 那就等待 咯 condition.await(); }else { System.out.println(Thread.currentThread().getName() + "取钱:" + drawMoney); //true 执行取钱的操作 balance -= drawMoney; System.out.println("账户余额为:" + balance); //取完钱 , 改flag flag = false; //唤醒其他线程 condition.signalAll(); } } catch (InterruptedException e) { e.printStackTrace(); }finally { lock.unlock();//释放锁 } } //存钱 public void save(double saveMoney) { lock.lock();//加锁 try { if(flag) {//true 标识有人存钱了 , 存钱方法阻塞 condition.await(); } else { // false 没钱 , 开始存钱 System.out.println(Thread.currentThread().getName() + "存款:" + saveMoney); balance += saveMoney; System.out.println("账户余额为:" + balance); //存完钱 , 改flag flag = true; //唤醒其他线程 condition.signalAll(); } } catch (InterruptedException e) { e.printStackTrace(); }finally { lock.unlock();//放锁 } } public String getAccount() { return account; } public void setAccount(String account) { this.account = account; } }
package com.example.demo.thread; public class DrawThread extends Thread{ private Account account;//账号 private double drawMoney;//想要划扣的钱 public DrawThread(String name , Account account, double drawMoney) { super(name); this.account = account; this.drawMoney = drawMoney; } public void run() { for(int i = 0 ; i < 100; i++) {//重复执行取钱的操作 account.draw(drawMoney); } } }
package com.example.demo.thread; public class SaveThread extends Thread{ private Account account;//账号 private double saveMoney;//想要存的钱 public SaveThread(String name , Account account , double saveMoney) { super(name); this.account = account; this.saveMoney = saveMoney; } public void run() { //重复执行存钱的操作 for(int i = 0 ; i < 100 ; i++) { account.save(saveMoney); } } }
package com.example.demo.thread; public class Test { public static void main(String[] args) { Account account = new Account("123456",0); new DrawThread("取钱者:", account, 500).start(); new SaveThread("存钱者-A", account, 500).start(); new SaveThread("存钱者-B", account, 500).start(); new SaveThread("存钱者-C", account, 500).start(); } }