标签:
java.util.concurrent.locks
Interface Condition
Condition类似于传统的wait、notify/notifyAll方法(这些方法需要内部监听器)。
Condition是在Lock之下,换句话说,有了Lock才可能产生Condition。在一个Lock之下可以生成几个Condition,从而可以使得因某个
Condition而阻塞的线程只能由相应的Condition唤醒。
比如,假设我们拥有一个支持取数据(take)和写数据(put)的缓存。如果take方法操作一个空的缓存,线程将会阻塞直到缓存中有数据项可用;
如果put方法试图操作一个满的缓存,线程将会阻塞知道用可用的空间。
1 class BoundedBuffer { 2 final Lock lock = new ReentrantLock(); 3 final Condition notFull = lock.newCondition(); 4 final Condition notEmpty = lock.newCondition(); 5 6 final Object[] items = new Object[100]; 7 int putptr, takeptr, count; 8 9 public void put(Object x) throws InterruptedException { 10 lock.lock(); 11 try { 12 while (count == items.length) 13 notFull.await(); 14 items[putptr] = x; 15 if (++putptr == items.length) putptr = 0; 16 ++count; 17 notEmpty.signal(); 18 } finally { 19 lock.unlock(); 20 } 21 } 22 23 public Object take() throws InterruptedException { 24 lock.lock(); 25 try { 26 while (count == 0) 27 notEmpty.await(); 28 Object x = items[takeptr]; 29 if (++takeptr == items.length) takeptr = 0; 30 --count; 31 notFull.signal(); 32 return x; 33 } finally { 34 lock.unlock(); 35 } 36 } 37 }
程序分析:
1、这里设置了两个条件notFull、notEmpty,当容器满了,就不满足notFull了,因此notFull.await,使得线程阻塞;notFull条件的阻塞,只能由notFull条件唤醒。
同理,notEmpty,当容器为空的时候,就不满足条件notEmpty了,因此notEmpty.await,使得线程阻塞,notEmpty条件的阻塞,只能由notEmpty条件唤醒。
2、判断边界值,从而判断条件是否满足,用的是while而不能是if。这是因为当线程被唤起后,还要检测条件是否满足,如果用if就不能达到这种效果,而会产生意想不到的
情况。比如,假设现在容器的大小为5。此时有10个写数据的线程来写数据,前面5个写线程都能正常往容器里面写数据,当容器满了以后接下来的线程就会不满足条件
notFull而放弃锁等待(await),因此会有5个线程阻塞于此。如果现在调用notFull.singalAll方法将所有不满足notFull条件而阻塞的线程都唤醒,那么缓存就会比它固定大小
多4个(造成缓存溢出)。当然,现在如果仅仅是调用的notFull.single,之所以会执行到这一步就是因为已经消费了而且只能唤醒一个线程,那么肯定会满足notFull条件,没有必要去进行检查。
标签:
原文地址:http://www.cnblogs.com/feijishuo/p/4538559.html