Condition

来源:互联网 发布:java程序员委培班 编辑:程序博客网 时间:2024/04/27 14:24

Ojbect:

           wait\notify\notifyAll

Condition

           await\signal\signalAll

 

Condition接口API里使用两个condition是否有必要?

 

class BoundedBuffer {    final Lock lock = new ReentrantLock();    final Condition notFull = lock.newCondition();    final Condition notEmpty = lock.newCondition();    final Object[] items = new Object[100];    int putptr,    takeptr,    count;    public void put(Object x) throws InterruptedException {        lock.lock();        try {            while (count == items.length) notFull.await();            items[putptr] = x;            if (++putptr == items.length) putptr = 0; ++count;            notEmpty.signal();        } finally {            lock.unlock();        }    }    public Object take() throws InterruptedException {        lock.lock();        try {            while (count == 0) notEmpty.await();            Object x = items[takeptr];            if (++takeptr == items.length) takeptr = 0; --count;            notFull.signal();            return x;        } finally {            lock.unlock();        }    }}

 有必要,应为这样写程序会更加清晰,比以前使用Object的wait/notify。 一个Condition代表一种条件,这个条件里面有一个链表,那么2个条件就有2条等待链表。 只要在等待的队列上被唤醒才能继续,如果同时被2个条件控制,那么就要分别被2个唤醒才行,这么写的好处是粒度细,控制更精细,不像Object的是粗粒度的。

 

请问用一个Condition是不是可以达到同样的效果呢? 当然可以,结构上没那么清晰了,没有JDK1.5的并发之前还不是用Object提供的wait写生产者消费者队列的 不过,同一个队列关联多个条件断言,用signal就危险了,要用sinalAll

 

内置锁对象只有一个条件队列,显式锁可以通过newCondition方法创建多个条件队列,这样就可以避免不同的条件断言关联同一个条件队列造成的问题。

 

 

有多个线程往里面存数据和从里面取数据,其队列(先进先出后进后出)能缓存的最大数值是capacity,多个线程间是互斥的,当缓存队列中存储的值达到capacity时,将写线程阻塞,并唤醒读线程,当缓存队列中存储的值为0时,将读线程阻塞,并唤醒写线程

 

 

这就是多个Condition的强大之处,假设缓存队列中已经存满,那么阻塞的肯定是写线程,唤醒的肯定是读线程,相反,阻塞的肯定是读线程,唤醒的肯定是写线程,那么假设只有一个Condition会有什么效果呢,缓存队列中已经存满,这个Lock不知道唤醒的是读线程还是写线程了,如果唤醒的是读线程,皆大欢喜,如果唤醒的是写线程,那么线程刚被唤醒,又被阻塞了,这时又去唤醒,这样就浪费了很多时间!

 

ArrayBlockingQueue中也使用了这种技术。

Condition 条件变量,线程通信更高效的方式

 

 

 

0 0
原创粉丝点击