一.
现在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();
}
}