下面的代码是从拍摄的JavaDoc的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();
}
}
}
想象一下,2个线程, 消费者和生产者 ,使用一个take
,一个put
上的单个实例BoundedBuffer
。
比方说, 消费者先行,运行take()
中,他锁定了lock
,现在环上notEmpty.await();
。
现在如何才能生产者可能进入put()
方法经过锁紧的lock
,这是已经被消费者持有?
我缺少的是在这里吗? 在lock
“临时解除”,而线程正在等待它的条件之一? 又是什么锁的重入的意思是,到底是什么?
这两种Lock
和synchronized
允许一个线程等待时放弃锁定,而另一个线程可以获取锁。 停止等待,一个线程必须重新获取锁。
注意:他们没有完全释放它,如果你需要一个堆栈跟踪,你可以有这似乎举行一次锁定多个线程,但在大多数人会运行(其余部分将被阻塞)
从Condition.await()
与此条件相关的锁以原子方式释放,并且当前线程的线程调度目的就退出,一直处于休眠状态的四两件事发生对象:
- 一些其它线程调用信号()方法为这个条件和当前的线程正好被选择作为被唤醒线程; 要么
- 一些其它线程调用此条件下的signalAll()方法; 要么
- 其他某个线程中断当前线程,并且支持中断线程的挂起; 要么
- “虚假唤醒”的发生。
在所有情况下,这种方法才能返回当前线程必须重新获取与此条件有关的锁。 当线程返回时,可以保证它保持此锁
至于重入,这意味着持有一定的锁的线程可以再次重新获得相同的锁。 如果情况并非如此,一个synchronized
方法就不能调用另一个synchronized
同一个对象的方法。
重入不涉及您的问题的理解。
我测试下面的代码与单个监视器和下面始终执行更好 - 测试2芯机上,成色性能低于10-15%的平均
final Object sync = new Object();
AtomicInteger add=new AtomicInteger();
AtomicInteger remove=new AtomicInteger();
final Object[] items = new Object[1];
int putptr, takeptr, count;
public void add(Object x) throws InterruptedException {
add.incrementAndGet();
synchronized (sync) {
while (count == items.length)
sync.wait();
items[putptr] = x;
if (++putptr == items.length) putptr = 0;
++count;
sync.notify();
}
}
public Object remove() throws InterruptedException {
remove.incrementAndGet();
synchronized (sync) {
while (count == 0)
sync.wait();
Object x = items[takeptr];
if (++takeptr == items.length) takeptr = 0;
--count;
sync.notify();
return x;
}
}
public static void main(String[] args) {
final BoundedBuffer bf=new BoundedBuffer();
Thread put =new Thread(){
public void run(){
try {
while(true)
bf.add(new Object());
} catch (InterruptedException e) {
}
}
};
put.start();
Thread take= new Thread(){
public void run(){
try {
while(true)
bf.remove();
} catch (InterruptedException e) {
}
}
};
take.start();
try {
Thread.sleep(1000L);
put.interrupt();
take.interrupt();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("add:"+bf.add);
System.out.println("remove:"+bf.remove);