可中断获取锁与超时等待获取锁源码分析
2020-09-25 16:35
260 查看
可中断式获取锁
可响应中断式锁可调用方法lock.lockInterruptibly();该方法的底层会调用AQS的acqireInterruptibly方法;
acquireInterruptibly()方法:
public final void acquireInterruptibly(int arg)
throws InterruptedException {
//这里会先检查是否有被中断,如果有则抛出一个中断异常
//否则尝试去获取同步状态,成功直接退出,失败则进入doAcquireInterruptibly(arg)方法
if (Thread.interrupted())
throw new InterruptedException();
if (!tryAcquire(arg))
doAcquireInterruptibly(arg);
}
doAcquireInterruptibly()方法:
如果当前线程的前驱节点为队头时,尝试获取同步状态
若获取成功则将队头节点出队,当前线程置为持有锁线程,并将队头指针指向当前线程所封装的节点,否则不断自旋直到获取成功或者线程被中断
/**
* Acquires in exclusive interruptible mode.
* @param arg the acquire argument
*/
private void doAcquireInterruptibly(int arg)
throws InterruptedException {
//尝试将节点插入到同步队列
final Node node = addWaiter(Node.EXCLUSIVE);
boolean failed = true;
try {
for (;;) {
//取当前节点的前驱节点
final Node p = node.predecessor();
//如果前驱节点为头结点,且成功获取同步状态则将持有锁线程
//置为当前线程,并将队头节点出队
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null; // help GC
failed = false;
return;
}
//获取同步状态失败,线程进入等待状态等待获取独占式
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
//线程被阻塞时若检测到中断抛出中断异常后退出。
throw new InterruptedException();
}
} finally {
//获取同步状态失败将当前节点取消
if (failed)
cancelAcquire(node);
}
}
超时等待获取锁(tryAcquireNanos()方法)
调用lock.tryLock(timeout,TimeUnit)方式
boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
超时等待锁的返回条件:在指定时间内获取到锁在指定时间内没有获取到锁在指定时间内被中断
public boolean tryLock(long timeout, TimeUnit unit)
throws InterruptedException {
return sync.tryAcquireNanos(1, unit.toNanos(timeout));
}
该方法调用AQS的tryAcquireNanos()方法:先判断是否被中断,然后尝试获取同步状态
如果成功则直接返会,否则进入到doAcquireNanos()方法:
public final boolean tryAcquireNanos(int arg, long nanosTimeout)
throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
return tryAcquire(arg) ||
doAcquireNanos(arg, nanosTimeout);
}
5ae
doAcquireNanos()方法:
/**
* Acquires in exclusive timed mode.
*
* @param arg the acquire argument
* @param nanosTimeout max wait time
* @return {@code true} if acquired
*/
private boolean doAcquireNanos(int arg, long nanosTimeout)
throws InterruptedException {
//如果设置的时间不合法,直接返回
if (nanosTimeout <= 0L)
return false;
//计算截止时间
final long deadline = System.nanoTime() + nanosTimeout;
//尝试将当前节点插入到同步队列
final Node node = addWaiter(Node.EXCLUSIVE);
boolean failed = true;
try {
for (;;) {
final Node p = node.predecessor();
//当前线程获得锁出队
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null; // help GC
failed = false;
return true;
}
//重新计算超时时间
nanosTimeout = deadline - System.nanoTime();
//如果超时直接返回
if (nanosTimeout <= 0L)
return false;
//线程阻塞等待
if (shouldParkAfterFailedAcquire(p, node) &&
nanosTimeout > spinForTimeoutThreshold)
LockSupport.parkNanos(this, nanosTimeout);
//若线程被中断则抛出中断异常
if (Thread.interrupted())
throw new InterruptedException();
}
} finally {
if (failed)
cancelAcquire(node);
}
}
最后
感谢大家看到这里,文章有不足,欢迎大家指出;如果你觉得写得不错,那就给我一个赞吧。
也欢迎大家关注我的公众号:程序员麦冬,麦冬每天都会分享java相关技术文章或行业资讯,欢迎大家关注和转发文章!
相关文章推荐
- JAVA并发编程学习笔记之AQS源码分析(超时、中断与其他)
- JAVA并发编程学习笔记之AQS源码分析(超时、中断与其他)
- 基于ReentrantLock的AQS的源码分析(独占、非中断、不超时部分)
- AQS源码分析(超时、中断与其他)
- uC/OS-II内核超时等待机制的分析
- 分析linux中断源码初始化
- Libevent源码分析-----超时event的处理
- C编程获取指定网卡网络数据包并分析(附C语言源码)
- Android 获取Root权限之后的静默安装实现 代码示例分析&&源码下载
- 第二人生的源码分析(四十六)获取纹理图片的线程
- libevent 源码分析:min_heap带来的超时机制
- springMVC源码分析--DispatcherServlet请求获取及处理
- linux中断源码分析 - 初始化(二)
- Libevent源码分析-----超时event的处理
- 通过一个简单的数据库连接池分析一下“等待超时模式”
- RxPermissions源码分析:使用RxJava处理Android 6.0运行时动态权限获取
- springMVC源码分析--AbstractHandlerMethodMapping获取url和HandlerMethod对应关系(十)
- docker 源码分析 四(基于1.8.2版本),Docker镜像的获取和存储
- Raw-OS源码分析之信号量释放与获取
- 等待队列源码分析