Java8 ReentrantLock Condition运用
程序员文章站
2022-03-19 15:31:20
Java8 ReentrantLock Condition在LinkedBlockingQueue中的使用场景1.持有的锁2.插入元素3.获取元素4.经验总结在LinkedBlockingQueue中的使用场景下面以LinkedBlockingQueue为例,分析ReentrantLock和Condition的作用。1.持有的锁/** Lock held by take, poll, etc */private final ReentrantLock takeLock = new Reentra...
Java8 ReentrantLock Condition运用
在LinkedBlockingQueue中的使用场景
下面以LinkedBlockingQueue为例,分析ReentrantLock和Condition的使用。
1.持有的锁
/** Lock held by take, poll, etc */
private final ReentrantLock takeLock = new ReentrantLock(); //获取元素锁
/** Wait queue for waiting takes */
private final Condition notEmpty = takeLock.newCondition(); //队列非空条件
/** Lock held by put, offer, etc */
private final ReentrantLock putLock = new ReentrantLock(); //插入元素锁
/** Wait queue for waiting puts */
private final Condition notFull = putLock.newCondition(); //队列未满条件
2.插入元素
public boolean offer(E e, long timeout, TimeUnit unit)
throws InterruptedException {
if (e == null) throw new NullPointerException(); //若插入空元素,抛出空指针异常
long nanos = unit.toNanos(timeout); //超时时间转换为时间戳
final int c;
final ReentrantLock putLock = this.putLock; //插入元素锁
final AtomicInteger count = this.count; //队列长度
putLock.lockInterruptibly(); //插入元素锁加锁
try {
while (count.get() == capacity) { //若队列已满,循环等待
if (nanos <= 0L) //若方法执行超时
return false; //返回false,插入元素失败
nanos = notFull.awaitNanos(nanos); //释放锁和CPU资源,等待唤醒,若被唤醒,继续while循环
}
enqueue(new Node<E>(e)); //若队列未满,且未超时,在队尾插入元素
c = count.getAndIncrement(); //获取之前的队列长度,然后将队列长度+1
if (c + 1 < capacity) //若队列未满
notFull.signal(); //唤醒notFull
} finally {
putLock.unlock(); //释放插入元素锁
}
if (c == 0) //如果之前的队列长度为0
signalNotEmpty(); //插入元素后,唤醒notEmpty
return true; //返回true,插入元素成功
}
3.获取元素
public E poll(long timeout, TimeUnit unit) throws InterruptedException {
final E x;
final int c;
long nanos = unit.toNanos(timeout); //超时时间转换为时间戳
final AtomicInteger count = this.count; //队列长度
final ReentrantLock takeLock = this.takeLock; //获取元素锁
takeLock.lockInterruptibly(); //获取元素锁加锁
try {
while (count.get() == 0) { //若队列为空,循环等待
if (nanos <= 0L) //若方法执行超时
return null; //返回null,获取元素失败
nanos = notEmpty.awaitNanos(nanos); //释放锁和CPU资源,等待唤醒,若被唤醒,继续while循环
}
x = dequeue(); //若队列非空,且未超时,获取队列首元素并从队列删除
c = count.getAndDecrement(); //获取之前的队列长度,然后将队列长度-1
if (c > 1) //若队列非空
notEmpty.signal(); //唤醒notEmpty
} finally {
takeLock.unlock(); //释放获取元素锁
}
if (c == capacity) //如果之前的队列是满的
signalNotFull(); //获取元素后,唤醒notFull
return x; //返回获取的元素
}
4.经验总结
1. Condition:固定模式,配合while循环使用。1.等待资源满足条件退出循环;2.超时退出。
2. LinkedBlockingQueue的实现使用了takeLock、putLock,防止死循环,代码中避免同时获取两把锁,例如上面插入元素,释放putLock 锁之后再执行signalNotEmpty,获取takeLock锁。
本文地址:https://blog.csdn.net/weixin_43858151/article/details/111886086
推荐阅读
-
Java多线程中ReentrantLock与Condition详解
-
ReentrantLock等待通知机制Condition介绍
-
java并发编程——通过ReentrantLock,Condition实现银行存取款
-
Java8 ReentrantLock Condition运用
-
ReentrantLock和condition源码浅析(一)
-
ReentrantLock等待通知机制Condition介绍
-
解读可重入锁——ReentrantLock&AQS,java8
-
Java~多线程ReentrantLock类常用的十四个方法, 使用Condition实现多线程的顺序执行
-
Java并发编程:Lock&ReentrantLock&Condition
-
ReentrantLock,Condition