这个条件锁怎么进行理解呢。我觉得用生活中最常见的方式来理解会更好理解。reentrantlock的条件锁,生成一个条件,相当于生成了一把钥匙,每一把钥匙都可以开锁,也都可以加锁。如下
Condition aConditio = reentrantLock.newCondition();
Condition bConditio = reentrantLock.newCondition();
Condition cConditio = reentrantLock.newCondition();
相当于三把钥匙。而钥匙运行的逻辑是什么呢,就是一个条件能够正常运行需要满足的条件。我们将这样的一个模型放到生产者和消费者这里来看。
生产者:能够正常向“房间”中放东西的前提(条件)是什么——是这个房间是还有空间
消费者:能够正常从“房间”中取东西的前提(条件)是什么——是这个房间中有东西
我们的条件锁就出来了,就是如下haveSpaceConditionhaveDataCondition
那么对应的正常逻辑伪代码也就出来了
正常逻辑伪代码
public void put(data){
// 先加锁
reentrantlock.lock();
// 内部处理逻辑
doAddInner(data);
// 当放完东西之后,记得通知下说现在有数据了
haveDataCondition();
}
对应的消费者也是
public Object get(){
// 先加锁
reentranlock.lock();
// 内部获取数据
Object data = getFromInner();
// 取出来之后,记得通知对方有空间了
haveSpaceCondition();
}
在正常情况考虑完了之后,还需要考虑异常情况,就是在不能放数据的时候怎么办以及“房间”空了不能取怎么办,这种异常情况的处理
添加异常情况的逻辑伪代码
对生产者而言,异常情况是不能放东西了,就做异常处理(其实就是正常工作的条件锁阻塞)
public void put(data){
// 先加锁
reentrantlock.lock();
if(isFull()){
haveSpaceCondition.await();
}
// 内部处理逻辑
doAddInner(data);
// 当放完东西之后,记得通知下说现在有数据了
haveDataCondition.notifyall();
}
对消费者而言,异常情况,就是不能取了,就做异常处理(其实就是正常工作的条件锁阻塞)
public Object get(){
// 先加锁
reentranlock.lock();
if(isEmpty()){
haveDataCondition.await();
}
// 内部获取数据
Object data = getFromInner();
// 取出来之后,记得通知对方有空间了
haveSpaceCondition();
}
当学习完这样的锁之后再看生产者和消费者的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();
}
}
}
思维扩展
条件锁除了生产者消费者之外,更多能够使用到条件的地方,都可以采用上面的正常和异常处理逻辑的方式进行考虑,我们可以试试考虑,三个线程,两个不同的处理方式这种
a -> b -> c
这种处理看看,不知道是不是也是可以
参考:
https://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/locks/Condition.html
网友评论