一.
现在wait方法和notifyAll方法,我们比较纠结。为什么这么说,之前同步里面的锁是我们自定义的,比如this,obj,而现在这个锁是我们自己new的,并且是根据1.5之后的锁对象来完成的。
以前写this和obj时,wait方法和notifyAll方法都是在这个锁上进行的操作,现在锁没了,现在的锁是lock。这个wait方法还能去操作this么?确切说,wait方法不能操作this这个锁上的线程了,因为线程的锁换了。应该用lock锁上的方法了,有的人直接改成lock.wait();
这么理解是对的,但是写法上有点变化,升级完的东西和以前有些不一样。用锁上的wait绝对是正确的思想,因为我们知道这种监视器的方法要根据该监视器所监视线程来操作。看下面的句子,
现在来阐述一下上面的截图是什么意思,
就以前的截图中同步来讲,对于同步来讲,锁上只能有一组监视器方法。什么意思呢?假设我这个锁是this的话,这个this锁上只有这么一组wait,notify,notifyAll这个方法。每个锁上绑定一组,因为每个锁都是object这个类的子类,它就直接拿这么一组方法。之前我们说的r.wait,r就是锁,它里面只能有这么一组wait,notify。而到了新版本里面,有一点改变了,
condition将object中的方法进行了封装,将这组监视器(wait,notify,notifyAll)单独封装成一个condition对象,而一个lock锁上可以挂多个conditon,每个condition都有一组监视器,
在上图中,有个obj。它里面只有一组wait,notify,notifyAll方法,因为只有一个对象嘛,只有一组。这三个方法就可以对这个锁进行操作了。你这同步函数只有一个锁,可以一旦锁变成对象以后,这个锁上可以挂多个锁,它可以将监视器方法封装成conditon对象。
何为condition呢?
上图conditon对象中,有一组方法,而且这个conditon对象有很多组,它们同属于一个锁
换句话说,这些conditon的方法都能都可以作用到这个锁的线程上。
以前的时候,一个锁只有一组方法(wait,notify,notifyAll),现在一个锁上可以挂多个。之前讲述的时候,object是锁,也是对象,里面封装着锁和一组方法,现在是将锁和方法分开来,锁用lock来表示,而一组方法用condition封装成对象,方法对象可以有很多个同时挂在一个锁上。
condition和lock之间有什么关系么?
截图中显示,通过newConditon()方法,我们随时可以拿到监视器方法实例。
在condition类的方法中,重新表述了一下wait,notify,notifyAll三个方法。名称变化了,功能没变。
await,signal,signalAll三个方法。
以前的时候,在object类中,有一组wait,notify,notifyAll的方法。同时创建一个自定义的类Demo,作为锁,new Demo就是锁对象。这个Demo类继承了object类,也就具备了这样一组方法。要将锁对象放入同步函数或者同步代码块中。
现在,我们将object类中操作监视器的方法封装成condition对象。本来锁和方法是封装在一起的,现在都分开来封装成对象。
从截图中可以看到,一个lock锁上,可以建立多个conditon方法。一个锁上有两组监视器。每个监视器里都有之前谈论的三个方法。
lock的目的是为了替代同步,而conditon的目的是为了替代object中的方法。
监视器必须监视锁上的线程才可以。
现在回过来改写原先的代码,
原先根据object.wati()的写法,写成的lock.wait()要进行修改。
conditon是监视器,是lock这个锁上的,这个监视器会对这个lock锁上的线程进行操作。
截图中的程序被还原成最早的样子。
package t4; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /** * * @author 高小硕 * jdk1.5以后将同步和锁封装成对象 * * 并将操作锁的隐式方式定义到了该对象中。 * 将隐式动作变成了显示动作 * * Lock接口:出现替代了同步代码块或者同步函数。将同步的隐式锁操作变成现实锁操作 * 同时更为灵活。可以一个锁上加上多组监视器。 * * lock():获取锁 * unlock():释放锁,通常需要定义在finall代码块中 * * Condition接口:出现替代了Object中的wait notify notifyAll方法 * * 将这些监视器方法单独进行了封装,变成Condition监视器对象。 * 可以任意锁进行组合。 *await(); *signal(); *signalAll(); * * */ class Resource { private String name; private int count=1; private boolean flag=false; //创建一个锁对象 Lock lock = new ReentrantLock(); //通过已有的锁获取该锁上的监视器对象 //使用两个监视器 Condition producer_con = lock.newCondition(); Condition consumber_con = lock.newCondition(); public void set(String name) { lock.lock(); try { while(flag) // try{wait();}catch(InterruptedException e){} try{producer_con.await();}catch(InterruptedException e){} this.name=name+count; count++;//2 3 4 System.out.println(Thread.currentThread().getName()+"...生产者..."+this.name); flag=true; consumber_con.signal();//唤醒对方的线程 } finally { lock.unlock(); } } public void out() { lock.lock(); try { while(!flag) // try{wait();}catch(Exception e){} try{consumber_con.await();}catch(InterruptedException e){} System.out.println(Thread.currentThread().getName()+".....消费者......"+this.name); flag=false; producer_con.signal(); } finally { lock.unlock(); } } } class Producer implements Runnable { private Resource r; public Producer(Resource r) { this.r=r; } public void run() { while(true) { r.set("烤鸭"); } } } class Consumer implements Runnable { private Resource r; public Consumer(Resource r) { this.r=r; } public void run() { while(true) { r.out(); } } } public class LockProducerConsumer { public static void main(String[] args) { Resource r=new Resource(); Producer pro=new Producer(r); Consumer con=new Consumer(r); Thread t1=new Thread(pro); Thread t2=new Thread(pro); Thread t3=new Thread(con); Thread t4=new Thread(con); t1.start(); t2.start(); t3.start(); t4.start(); } }