Condition 问题 很不能理解为什么要用2个Condition

KPRF2009 2012-12-06 11:29:30


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();
}
}
}



Condition 问题 很不能理解为什么要用2个Condition
...全文
187 3 打赏 收藏 转发到动态 举报
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
龙四 2012-12-08
  • 打赏
  • 举报
回复
当然可以使用一个Condition,但要注意,使用一个Condition的时候就要使用signalAll方法了,这换唤醒所有等待的线程,而最终可能只有一个线程的条件满足了,比如buffer现在是空的,有100个线程在等待,现在加入一个元素,唤醒了100个线程,线程从wait中醒来需要重新获取锁,这100个线程就要竞争同一把锁,而最终只有一个线程能消费这个元素,其它99个线程醒来后又继续while (count == 0)成立,继续await,在高并发下,这是非常大的竞争与上下文切换开销 为什么一个Condition就必须用notifyAll?因为这个Condition是作为两个条件断言使用的。 假设有buffer的长度是10,现在10个元素都被消费完了,且还有15个线程在上面等待 现在有10个线程各往里put一个元素,虽然每put一次都会做唤醒操作,但是存在唤醒的线程一直竞争不到锁的情况,于是那15个线程还在等待,而10个线程很幸运,在与那15个线程的竞争过程中都先获取到锁了,且把元素放进去了,这是bufer里就有10个元素了,也就是满了,put的线程又来了,这次又来了10个,他们都需要wait,现在是什么场景?有10个元素,15个线程在等待获取锁然后拿到元素,10个线程等待往buffer里塞东西,如果只有一个Condition,且使用的是signal而不是signalAll,在消费了一个元素后,本来该唤醒一个生产线程,而它却有可能唤醒的还是消费线程,因为消费线程和生产线程都在同一个条件队列里等待,这就出问题了。 如果LZ读过《Java concurrency in practice》第14章,将会看到很多BoundedBuffer的实现 http://www.ticmy.com/?p=219
KPRF2009 2012-12-07
  • 打赏
  • 举报
回复
引用 1 楼 limit111 的回复:
所谓condition就是指条件嘛,一般是用来阻塞线程的,或者说满足某个条件才能让线程继续往下运行。 这里一个是表示满的状态,一个表示空的状态。
如果用一个不可以吗? 为什么不可以?
limit111 2012-12-07
  • 打赏
  • 举报
回复
所谓condition就是指条件嘛,一般是用来阻塞线程的,或者说满足某个条件才能让线程继续往下运行。 这里一个是表示满的状态,一个表示空的状态。

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧